diff options
Diffstat (limited to 'src/service/cadet')
40 files changed, 18852 insertions, 0 deletions
diff --git a/src/service/cadet/.gitignore b/src/service/cadet/.gitignore new file mode 100644 index 000000000..bed27a3d3 --- /dev/null +++ b/src/service/cadet/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | gnunet-service-cadet | ||
2 | test_cadet_local_mq | ||
diff --git a/src/service/cadet/Makefile.am b/src/service/cadet/Makefile.am new file mode 100644 index 000000000..0046ffc70 --- /dev/null +++ b/src/service/cadet/Makefile.am | |||
@@ -0,0 +1,81 @@ | |||
1 | # This Makefile.am is in the public domain | ||
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 | |||
23 | lib_LTLIBRARIES = \ | ||
24 | libgnunetcadet.la | ||
25 | |||
26 | libgnunetcadet_la_SOURCES = \ | ||
27 | cadet_api.c \ | ||
28 | cadet_api_drop_message.c \ | ||
29 | cadet_api_get_channel.c \ | ||
30 | cadet_api_get_path.c \ | ||
31 | cadet_api_list_peers.c \ | ||
32 | cadet_api_list_tunnels.c \ | ||
33 | cadet_api_helper.c | ||
34 | libgnunetcadet_la_LIBADD = \ | ||
35 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
36 | $(XLIB) \ | ||
37 | $(LTLIBINTL) | ||
38 | libgnunetcadet_la_LDFLAGS = \ | ||
39 | $(GN_LIB_LDFLAGS) \ | ||
40 | -version-info 7:0:0 | ||
41 | |||
42 | gnunet_service_cadet_SOURCES = \ | ||
43 | gnunet-service-cadet.c gnunet-service-cadet.h \ | ||
44 | gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ | ||
45 | gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ | ||
46 | gnunet-service-cadet_core.c gnunet-service-cadet_core.h \ | ||
47 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ | ||
48 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ | ||
49 | gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \ | ||
50 | gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \ | ||
51 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h | ||
52 | gnunet_service_cadet_LDADD = \ | ||
53 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
54 | $(top_builddir)/src/service/core/libgnunetcore.la \ | ||
55 | $(top_builddir)/src/service/dht/libgnunetdht.la \ | ||
56 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
57 | $(top_builddir)/src/service/transport/libgnunettransportapplication.la \ | ||
58 | $(top_builddir)/src/service/peerstore/libgnunetpeerstore.la \ | ||
59 | $(top_builddir)/src/lib/hello/libgnunethello.la \ | ||
60 | $(top_builddir)/src/lib/block/libgnunetblock.la | ||
61 | if LINUX | ||
62 | gnunet_service_cadet_LDFLAGS = -lrt \ | ||
63 | $(GN_LIBINTL) | ||
64 | endif | ||
65 | |||
66 | |||
67 | test_cadet_local_mq_SOURCES = \ | ||
68 | test_cadet_local_mq.c | ||
69 | test_cadet_local_mq_LDADD = \ | ||
70 | libgnunetcadet.la \ | ||
71 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
72 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
73 | |||
74 | if ENABLE_TEST_RUN | ||
75 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
76 | TESTS = $(check_PROGRAMS) | ||
77 | endif | ||
78 | |||
79 | EXTRA_DIST = \ | ||
80 | cadet.h cadet_protocol.h \ | ||
81 | test_cadet.conf | ||
diff --git a/src/service/cadet/TODO b/src/service/cadet/TODO new file mode 100644 index 000000000..06567b0ad --- /dev/null +++ b/src/service/cadet/TODO | |||
@@ -0,0 +1,36 @@ | |||
1 | - URGENT: | ||
2 | + if 'client-not-ready', we do not ACK at all, and sender keeps | ||
3 | retransmitting again and again; would be good to do flow-control notification instead | ||
4 | of not ACKing that we got the data but are simply not ready for more! | ||
5 | + Congestion/flow control (CHANNEL): | ||
6 | estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
7 | (and figure out how/where to use this!) | ||
8 | |||
9 | - HIGH: revisit handling of 'unbuffered' traffic! (CHANNEL/TUNNEL) | ||
10 | (need to push down through tunnel into connection selection); | ||
11 | At Tunnel-level, try to create connections that match channel | ||
12 | preferences (buffered/unbuffered) and select connections for | ||
13 | channel traffic that match channel preferences. | ||
14 | BUT: not sure this is ideal, discloses traffic type to | ||
15 | routers. We don't want that! (Maybe revise decision to do this?) | ||
16 | |||
17 | - HIGH: revisit handling of 'buffered' traffic: 4 is a rather small buffer; (CHANNEL) | ||
18 | maybe reserve more bits in 'options' to allow for buffer size control? | ||
19 | Or: maybe even better, calculated required buffer size based on latency | ||
20 | and throughput (and available memory) | ||
21 | |||
22 | - HIGH: if we receive BROKEN messages, cut down corresponding PATH (up to the | ||
23 | point of breakage) as well as connection/route (CORE) | ||
24 | |||
25 | - OPTIMIZATION: proper connection evaluation during connection management: | ||
26 | + TUNNELS: | ||
27 | * consider quality of current connection set when deciding | ||
28 | how often to do maintenance | ||
29 | * interact with PEER to drive DHT GET/PUT operations based | ||
30 | on how much we like our connections | ||
31 | |||
32 | |||
33 | - OPTIMIZATION: optimize stopping/restarting DHT search to situations | ||
34 | where we actually need it (i.e. not if we have a direct connection, | ||
35 | or if we already have plenty of good short ones, or maybe even | ||
36 | to take a break if we have some connections and have searched a lot (?)) (PEER) | ||
diff --git a/src/service/cadet/cadet.conf.in b/src/service/cadet/cadet.conf.in new file mode 100644 index 000000000..8f700951c --- /dev/null +++ b/src/service/cadet/cadet.conf.in | |||
@@ -0,0 +1,53 @@ | |||
1 | [cadet] | ||
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/service/cadet/cadet.h b/src/service/cadet/cadet.h new file mode 100644 index 000000000..e8caa7d35 --- /dev/null +++ b/src/service/cadet/cadet.h | |||
@@ -0,0 +1,578 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001 - 2011 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Bartlomiej Polot | ||
23 | * @file cadet/cadet.h | ||
24 | */ | ||
25 | |||
26 | #ifndef CADET_H_ | ||
27 | #define CADET_H_ | ||
28 | |||
29 | #ifdef __cplusplus | ||
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_core_service.h" | ||
59 | #include "gnunet_cadet_service.h" | ||
60 | #include "gnunet_protocols.h" | ||
61 | #include "gnunet_cadet_service.h" | ||
62 | |||
63 | /******************************************************************************/ | ||
64 | /************************** CONSTANTS ******************************/ | ||
65 | /******************************************************************************/ | ||
66 | |||
67 | /** | ||
68 | * Minimum value for channel IDs of local clients. | ||
69 | */ | ||
70 | #define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000U | ||
71 | |||
72 | /** | ||
73 | * FIXME. | ||
74 | */ | ||
75 | #define HIGH_PID 0xFF000000 | ||
76 | |||
77 | /** | ||
78 | * FIXME. | ||
79 | */ | ||
80 | #define LOW_PID 0x00FFFFFF | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Test if the two PIDs (of type `uint32_t`) are in the range where we | ||
85 | * have to worry about overflows. This is the case when @a pid is | ||
86 | * large and @a max is small, useful when comparing @a pid smaller | ||
87 | * than @a max. | ||
88 | */ | ||
89 | #define PID_OVERFLOW(pid, max) (((pid) > HIGH_PID) && ((max) < LOW_PID)) | ||
90 | |||
91 | /******************************************************************************/ | ||
92 | /************************** MESSAGES ******************************/ | ||
93 | /******************************************************************************/ | ||
94 | |||
95 | GNUNET_NETWORK_STRUCT_BEGIN | ||
96 | |||
97 | /** | ||
98 | * Number uniquely identifying a channel of a client. | ||
99 | */ | ||
100 | struct GNUNET_CADET_ClientChannelNumber | ||
101 | { | ||
102 | /** | ||
103 | * Values for channel numbering. | ||
104 | * Local channel numbers given by the service (incoming) are | ||
105 | * smaller than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI. | ||
106 | * Local channel numbers given by the client (created) are | ||
107 | * larger than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI. | ||
108 | */ | ||
109 | uint32_t channel_of_client GNUNET_PACKED; | ||
110 | }; | ||
111 | |||
112 | /** | ||
113 | * Opaque handle to a channel. | ||
114 | */ | ||
115 | struct GNUNET_CADET_Channel | ||
116 | { | ||
117 | |||
118 | /** | ||
119 | * Other end of the channel. | ||
120 | */ | ||
121 | struct GNUNET_PeerIdentity peer; | ||
122 | |||
123 | /** | ||
124 | * Handle to the cadet this channel belongs to | ||
125 | */ | ||
126 | struct GNUNET_CADET_Handle *cadet; | ||
127 | |||
128 | /** | ||
129 | * Channel's port, if incoming. | ||
130 | */ | ||
131 | struct GNUNET_CADET_Port *incoming_port; | ||
132 | |||
133 | /** | ||
134 | * Any data the caller wants to put in here, used for the | ||
135 | * various callbacks (@e disconnects, @e window_changes, handlers). | ||
136 | */ | ||
137 | void *ctx; | ||
138 | |||
139 | /** | ||
140 | * Message Queue for the channel (which we are implementing). | ||
141 | */ | ||
142 | struct GNUNET_MQ_Handle *mq; | ||
143 | |||
144 | /** | ||
145 | * Task to allow mq to send more traffic. | ||
146 | */ | ||
147 | struct GNUNET_SCHEDULER_Task *mq_cont; | ||
148 | |||
149 | /** | ||
150 | * Pending envelope with a message to be transmitted to the | ||
151 | * service as soon as we are allowed to. Should only be | ||
152 | * non-NULL if @e allow_send is 0. | ||
153 | */ | ||
154 | struct GNUNET_MQ_Envelope *pending_env; | ||
155 | |||
156 | /** | ||
157 | * Window change handler. | ||
158 | */ | ||
159 | GNUNET_CADET_WindowSizeEventHandler window_changes; | ||
160 | |||
161 | /** | ||
162 | * Disconnect handler. | ||
163 | */ | ||
164 | GNUNET_CADET_DisconnectEventHandler disconnects; | ||
165 | |||
166 | /** | ||
167 | * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound. | ||
168 | */ | ||
169 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
170 | |||
171 | /** | ||
172 | * How many messages are we allowed to send to the service right now? | ||
173 | */ | ||
174 | unsigned int allow_send; | ||
175 | }; | ||
176 | |||
177 | /** | ||
178 | * Message for a client to create and destroy channels. | ||
179 | */ | ||
180 | struct GNUNET_CADET_PortMessage | ||
181 | { | ||
182 | /** | ||
183 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN | ||
184 | * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE | ||
185 | * | ||
186 | * Size: sizeof(struct GNUNET_CADET_ChannelMessage) | ||
187 | */ | ||
188 | struct GNUNET_MessageHeader header; | ||
189 | |||
190 | /** | ||
191 | * Port to open/close. | ||
192 | */ | ||
193 | struct GNUNET_HashCode port GNUNET_PACKED; | ||
194 | }; | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Message for a client to create channels. | ||
199 | */ | ||
200 | struct GNUNET_CADET_LocalChannelCreateMessage | ||
201 | { | ||
202 | /** | ||
203 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE | ||
204 | * | ||
205 | * Size: sizeof(struct GNUNET_CADET_ChannelOpenMessageMessage) | ||
206 | */ | ||
207 | struct GNUNET_MessageHeader header; | ||
208 | |||
209 | /** | ||
210 | * ID of a channel controlled by this client. | ||
211 | */ | ||
212 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
213 | |||
214 | /** | ||
215 | * Channel's peer | ||
216 | */ | ||
217 | struct GNUNET_PeerIdentity peer; | ||
218 | |||
219 | /** | ||
220 | * Port of the channel. | ||
221 | */ | ||
222 | struct GNUNET_HashCode port; | ||
223 | |||
224 | /** | ||
225 | * Options. | ||
226 | */ | ||
227 | uint32_t opt GNUNET_PACKED; | ||
228 | }; | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Message for or to a client to destroy tunnel. | ||
233 | */ | ||
234 | struct GNUNET_CADET_LocalChannelDestroyMessage | ||
235 | { | ||
236 | /** | ||
237 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY | ||
238 | */ | ||
239 | struct GNUNET_MessageHeader header; | ||
240 | |||
241 | /** | ||
242 | * ID of a channel controlled by this client. | ||
243 | */ | ||
244 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
245 | }; | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Message for cadet data traffic. | ||
250 | */ | ||
251 | struct GNUNET_CADET_LocalData | ||
252 | { | ||
253 | /** | ||
254 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA | ||
255 | */ | ||
256 | struct GNUNET_MessageHeader header; | ||
257 | |||
258 | /** | ||
259 | * ID of the channel | ||
260 | */ | ||
261 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
262 | |||
263 | /** | ||
264 | * Priority and preferences (an enum GNUNET_MQ_PriorityPreferences) | ||
265 | * of the message in NBO. | ||
266 | */ | ||
267 | uint32_t pp GNUNET_PACKED; | ||
268 | |||
269 | /** | ||
270 | * Payload follows | ||
271 | */ | ||
272 | }; | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Message to allow the client send more data to the service | ||
277 | * (always service -> client). | ||
278 | */ | ||
279 | struct GNUNET_CADET_LocalAck | ||
280 | { | ||
281 | /** | ||
282 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK | ||
283 | */ | ||
284 | struct GNUNET_MessageHeader header; | ||
285 | |||
286 | /** | ||
287 | * ID of the channel allowed to send more data. | ||
288 | */ | ||
289 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
290 | }; | ||
291 | |||
292 | |||
293 | /** | ||
294 | * Message to inform the client about channels in the service. | ||
295 | * | ||
296 | * TODO: split into two messages! | ||
297 | */ | ||
298 | struct GNUNET_CADET_LocalInfo | ||
299 | { | ||
300 | /** | ||
301 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL or | ||
302 | * #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER | ||
303 | */ | ||
304 | struct GNUNET_MessageHeader header; | ||
305 | |||
306 | /** | ||
307 | * ID of the channel allowed to send more data. | ||
308 | */ | ||
309 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
310 | |||
311 | /** | ||
312 | * ID of the destination of the channel (can be local peer). | ||
313 | */ | ||
314 | struct GNUNET_PeerIdentity peer; | ||
315 | }; | ||
316 | |||
317 | /** | ||
318 | * Message to drop another message of specific type. Used in test context | ||
319 | */ | ||
320 | struct GNUNET_CADET_RequestDropCadetMessage | ||
321 | { | ||
322 | |||
323 | /** | ||
324 | * Type: #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE | ||
325 | */ | ||
326 | struct GNUNET_MessageHeader header; | ||
327 | |||
328 | /** | ||
329 | * Type of the message this handler covers, in host byte order. | ||
330 | */ | ||
331 | uint16_t type; | ||
332 | |||
333 | /** | ||
334 | * ID of the channel we want to drop a message for. | ||
335 | */ | ||
336 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
337 | |||
338 | }; | ||
339 | |||
340 | /** | ||
341 | * Message to inform the client about channels in the service. | ||
342 | */ | ||
343 | struct GNUNET_CADET_RequestPathInfoMessage | ||
344 | { | ||
345 | /** | ||
346 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH | ||
347 | */ | ||
348 | struct GNUNET_MessageHeader header; | ||
349 | |||
350 | /** | ||
351 | * Always zero. | ||
352 | */ | ||
353 | uint32_t resered GNUNET_PACKED; | ||
354 | |||
355 | /** | ||
356 | * ID of the destination of the channel (can be local peer). | ||
357 | */ | ||
358 | struct GNUNET_PeerIdentity peer; | ||
359 | }; | ||
360 | |||
361 | |||
362 | /** | ||
363 | * Message to inform the client about channels in the service. | ||
364 | */ | ||
365 | struct GNUNET_CADET_ChannelInfoMessage | ||
366 | { | ||
367 | /** | ||
368 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL. | ||
369 | */ | ||
370 | struct GNUNET_MessageHeader header; | ||
371 | |||
372 | /** | ||
373 | * Root of the channel | ||
374 | */ | ||
375 | struct GNUNET_PeerIdentity root; | ||
376 | |||
377 | /** | ||
378 | * Destination of the channel | ||
379 | */ | ||
380 | struct GNUNET_PeerIdentity dest; | ||
381 | |||
382 | /* FIXME: expand! */ | ||
383 | }; | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Message to as the service about information on a channel. | ||
388 | */ | ||
389 | struct GNUNET_CADET_RequestChannelInfoMessage | ||
390 | { | ||
391 | /** | ||
392 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_CHANNEL. | ||
393 | */ | ||
394 | struct GNUNET_MessageHeader header; | ||
395 | |||
396 | /** | ||
397 | * Target of the channel. | ||
398 | */ | ||
399 | struct GNUNET_PeerIdentity target; | ||
400 | }; | ||
401 | |||
402 | |||
403 | /** | ||
404 | * Message to inform the client about one of the paths known to the service. | ||
405 | */ | ||
406 | struct GNUNET_CADET_LocalInfoPath | ||
407 | { | ||
408 | /** | ||
409 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH. | ||
410 | */ | ||
411 | struct GNUNET_MessageHeader header; | ||
412 | |||
413 | /** | ||
414 | * Offset of the peer that was requested. | ||
415 | */ | ||
416 | uint32_t off GNUNET_PACKED; | ||
417 | }; | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Message to inform the client about one of the peers in the service. | ||
422 | */ | ||
423 | struct GNUNET_CADET_LocalInfoPeers | ||
424 | { | ||
425 | /** | ||
426 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS | ||
427 | */ | ||
428 | struct GNUNET_MessageHeader header; | ||
429 | |||
430 | /** | ||
431 | * Number of paths. | ||
432 | */ | ||
433 | uint16_t paths GNUNET_PACKED; | ||
434 | |||
435 | /** | ||
436 | * Do we have a tunnel toward this peer? | ||
437 | */ | ||
438 | int16_t tunnel GNUNET_PACKED; | ||
439 | |||
440 | /** | ||
441 | * Shortest known path. | ||
442 | */ | ||
443 | uint32_t best_path_length GNUNET_PACKED; | ||
444 | |||
445 | /** | ||
446 | * ID of the peer (can be local peer). | ||
447 | */ | ||
448 | struct GNUNET_PeerIdentity destination; | ||
449 | }; | ||
450 | |||
451 | |||
452 | /** | ||
453 | * Message to inform the client about one of the tunnels in the service. | ||
454 | * | ||
455 | * TODO: split into two messages! | ||
456 | */ | ||
457 | struct GNUNET_CADET_LocalInfoTunnel | ||
458 | { | ||
459 | /** | ||
460 | * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL | ||
461 | * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS | ||
462 | */ | ||
463 | struct GNUNET_MessageHeader header; | ||
464 | |||
465 | /** | ||
466 | * Number of channels. | ||
467 | */ | ||
468 | uint32_t channels GNUNET_PACKED; | ||
469 | |||
470 | /** | ||
471 | * ID of the destination of the tunnel (can be local peer). | ||
472 | */ | ||
473 | struct GNUNET_PeerIdentity destination; | ||
474 | |||
475 | /** | ||
476 | * Number of connections. | ||
477 | */ | ||
478 | uint32_t connections GNUNET_PACKED; | ||
479 | |||
480 | /** | ||
481 | * Encryption state. | ||
482 | */ | ||
483 | uint16_t estate GNUNET_PACKED; | ||
484 | |||
485 | /** | ||
486 | * Connection state. | ||
487 | */ | ||
488 | uint16_t cstate GNUNET_PACKED; | ||
489 | |||
490 | /* If TUNNEL (no 'S'): struct GNUNET_CADET_ConnectionTunnelIdentifier connection_ids[connections] */ | ||
491 | /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */ | ||
492 | }; | ||
493 | |||
494 | |||
495 | GNUNET_NETWORK_STRUCT_END | ||
496 | |||
497 | |||
498 | /** | ||
499 | * @brief Translate a fwd variable into a string representation, for logging. | ||
500 | * | ||
501 | * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) | ||
502 | * | ||
503 | * @return String representing FWD or BCK. | ||
504 | */ | ||
505 | char * | ||
506 | GC_f2s (int fwd); | ||
507 | |||
508 | |||
509 | /** | ||
510 | * Check if one pid is bigger than other, accounting for overflow. | ||
511 | * | ||
512 | * @param bigger Argument that should be bigger. | ||
513 | * @param smaller Argument that should be smaller. | ||
514 | * | ||
515 | * @return True if bigger (arg1) has a higher value than smaller (arg 2). | ||
516 | */ | ||
517 | int | ||
518 | GC_is_pid_bigger (uint32_t bigger, uint32_t smaller); | ||
519 | |||
520 | |||
521 | /** | ||
522 | * Get the higher ACK value out of two values, taking in account overflow. | ||
523 | * | ||
524 | * @param a First ACK value. | ||
525 | * @param b Second ACK value. | ||
526 | * | ||
527 | * @return Highest ACK value from the two. | ||
528 | */ | ||
529 | uint32_t | ||
530 | GC_max_pid (uint32_t a, uint32_t b); | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Get the lower ACK value out of two values, taking in account overflow. | ||
535 | * | ||
536 | * @param a First ACK value. | ||
537 | * @param b Second ACK value. | ||
538 | * | ||
539 | * @return Lowest ACK value from the two. | ||
540 | */ | ||
541 | uint32_t | ||
542 | GC_min_pid (uint32_t a, uint32_t b); | ||
543 | |||
544 | |||
545 | /** | ||
546 | * Allocate a string with a hexdump of any binary data. | ||
547 | * | ||
548 | * @param bin Arbitrary binary data. | ||
549 | * @param len Length of @a bin in bytes. | ||
550 | * @param output Where to write the output (if *output be NULL it's allocated). | ||
551 | * | ||
552 | * @return The size of the output. | ||
553 | */ | ||
554 | size_t | ||
555 | GC_bin2s (void *bin, unsigned int len, char **output); | ||
556 | |||
557 | |||
558 | /** | ||
559 | * Convert a message type into a string to help debug | ||
560 | * Generated with: | ||
561 | * FIND: "#define ([^ ]+)[ ]*([0-9]+)" | ||
562 | * REPLACE: " case \2: return "\1"; break;" | ||
563 | * | ||
564 | * @param m Message type. | ||
565 | * | ||
566 | * @return Human readable string description. | ||
567 | */ | ||
568 | const char * | ||
569 | GC_m2s (uint16_t m); | ||
570 | |||
571 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
572 | { | ||
573 | #endif | ||
574 | #ifdef __cplusplus | ||
575 | } | ||
576 | #endif | ||
577 | |||
578 | #endif | ||
diff --git a/src/service/cadet/cadet_api.c b/src/service/cadet/cadet_api.c new file mode 100644 index 000000000..0bfb01868 --- /dev/null +++ b/src/service/cadet/cadet_api.c | |||
@@ -0,0 +1,1072 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | #define LOG(kind, ...) GNUNET_log_from (kind, "cadet-api", __VA_ARGS__) | ||
34 | |||
35 | /** | ||
36 | * Opaque handle to the service. | ||
37 | */ | ||
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 | */ | ||
202 | static void | ||
203 | destroy_channel (struct GNUNET_CADET_Channel *ch) | ||
204 | { | ||
205 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
206 | |||
207 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
208 | "Destroying channel %X of %p\n", | ||
209 | htonl (ch->ccn.channel_of_client), | ||
210 | h); | ||
211 | GNUNET_assert ( | ||
212 | GNUNET_YES == | ||
213 | GNUNET_CONTAINER_multihashmap32_remove (h->channels, | ||
214 | ntohl (ch->ccn.channel_of_client), | ||
215 | ch)); | ||
216 | if (NULL != ch->mq_cont) | ||
217 | { | ||
218 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | ||
219 | ch->mq_cont = NULL; | ||
220 | } | ||
221 | /* signal channel destruction */ | ||
222 | if (NULL != ch->disconnects) | ||
223 | ch->disconnects (ch->ctx, ch); | ||
224 | if (NULL != ch->pending_env) | ||
225 | GNUNET_MQ_discard (ch->pending_env); | ||
226 | GNUNET_MQ_destroy (ch->mq); | ||
227 | GNUNET_free (ch); | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Reconnect to the service, retransmit all information to try to restore the | ||
233 | * original state. | ||
234 | * | ||
235 | * @param h handle to the cadet | ||
236 | */ | ||
237 | static void | ||
238 | reconnect (struct GNUNET_CADET_Handle *h); | ||
239 | |||
240 | |||
241 | /** | ||
242 | * Function called during #reconnect_cbk() to (re)open | ||
243 | * all ports that are still open. | ||
244 | * | ||
245 | * @param cls the `struct GNUNET_CADET_Handle` | ||
246 | * @param id port ID | ||
247 | * @param value a `struct GNUNET_CADET_Channel` to open | ||
248 | * @return #GNUNET_OK (continue to iterate) | ||
249 | */ | ||
250 | static int | ||
251 | open_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value) | ||
252 | { | ||
253 | struct GNUNET_CADET_Handle *h = cls; | ||
254 | struct GNUNET_CADET_Port *port = value; | ||
255 | struct GNUNET_CADET_PortMessage *msg; | ||
256 | struct GNUNET_MQ_Envelope *env; | ||
257 | |||
258 | (void) id; | ||
259 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
260 | msg->port = port->id; | ||
261 | GNUNET_MQ_send (h->mq, env); | ||
262 | return GNUNET_OK; | ||
263 | } | ||
264 | |||
265 | |||
266 | /** | ||
267 | * Reconnect callback: tries to reconnect again after a failed previous | ||
268 | * connection | ||
269 | * | ||
270 | * @param cls closure (cadet handle) | ||
271 | */ | ||
272 | static void | ||
273 | reconnect_cbk (void *cls) | ||
274 | { | ||
275 | struct GNUNET_CADET_Handle *h = cls; | ||
276 | |||
277 | h->reconnect_task = NULL; | ||
278 | h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time); | ||
279 | reconnect (h); | ||
280 | GNUNET_CONTAINER_multihashmap_iterate (h->ports, &open_port_cb, h); | ||
281 | } | ||
282 | |||
283 | |||
284 | /** | ||
285 | * Notify the application about a change in the window size (if needed). | ||
286 | * | ||
287 | * @param ch Channel to notify about. | ||
288 | */ | ||
289 | static void | ||
290 | notify_window_size (struct GNUNET_CADET_Channel *ch) | ||
291 | { | ||
292 | if (NULL != ch->window_changes) | ||
293 | ch->window_changes (ch->ctx, | ||
294 | ch, /* FIXME: remove 'ch'? */ | ||
295 | ch->allow_send); | ||
296 | } | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Transmit the next message from our queue. | ||
301 | * | ||
302 | * @param cls Closure (channel whose mq to activate). | ||
303 | */ | ||
304 | static void | ||
305 | cadet_mq_send_now (void *cls) | ||
306 | { | ||
307 | struct GNUNET_CADET_Channel *ch = cls; | ||
308 | struct GNUNET_MQ_Envelope *env = ch->pending_env; | ||
309 | |||
310 | ch->mq_cont = NULL; | ||
311 | if (0 == ch->allow_send) | ||
312 | { | ||
313 | /* how did we get here? */ | ||
314 | GNUNET_break (0); | ||
315 | return; | ||
316 | } | ||
317 | if (NULL == env) | ||
318 | { | ||
319 | /* how did we get here? */ | ||
320 | GNUNET_break (0); | ||
321 | return; | ||
322 | } | ||
323 | ch->allow_send--; | ||
324 | ch->pending_env = NULL; | ||
325 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
326 | "Sending message on channel %s to CADET, new window size is %u\n", | ||
327 | GNUNET_i2s (&ch->peer), | ||
328 | ch->allow_send); | ||
329 | GNUNET_MQ_send (ch->cadet->mq, env); | ||
330 | GNUNET_MQ_impl_send_continue (ch->mq); | ||
331 | } | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Implement sending functionality of a message queue for | ||
336 | * us sending messages to a peer. | ||
337 | * | ||
338 | * Encapsulates the payload message in a #GNUNET_CADET_LocalData message | ||
339 | * in order to label the message with the channel ID and send the | ||
340 | * encapsulated message to the service. | ||
341 | * | ||
342 | * @param mq the message queue | ||
343 | * @param msg the message to send | ||
344 | * @param impl_state state of the implementation | ||
345 | */ | ||
346 | static void | ||
347 | cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | ||
348 | const struct GNUNET_MessageHeader *msg, | ||
349 | void *impl_state) | ||
350 | { | ||
351 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
352 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
353 | uint16_t msize; | ||
354 | struct GNUNET_MQ_Envelope *orig_env; | ||
355 | struct GNUNET_MQ_Envelope *env; | ||
356 | struct GNUNET_CADET_LocalData *cadet_msg; | ||
357 | enum GNUNET_MQ_PriorityPreferences pp; | ||
358 | |||
359 | if (NULL == h->mq) | ||
360 | { | ||
361 | /* We're currently reconnecting, pretend this worked */ | ||
362 | GNUNET_MQ_impl_send_continue (mq); | ||
363 | return; | ||
364 | } | ||
365 | orig_env = GNUNET_MQ_get_current_envelope (mq); | ||
366 | pp = GNUNET_MQ_env_get_options (orig_env); | ||
367 | |||
368 | /* check message size for sanity */ | ||
369 | msize = ntohs (msg->size); | ||
370 | if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE) | ||
371 | { | ||
372 | GNUNET_break (0); | ||
373 | GNUNET_MQ_impl_send_continue (mq); | ||
374 | return; | ||
375 | } | ||
376 | env = GNUNET_MQ_msg_nested_mh (cadet_msg, | ||
377 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
378 | msg); | ||
379 | cadet_msg->ccn = ch->ccn; | ||
380 | cadet_msg->pp = htonl ((uint32_t) pp); | ||
381 | GNUNET_assert (NULL == ch->pending_env); | ||
382 | ch->pending_env = env; | ||
383 | if (0 < ch->allow_send) | ||
384 | ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch); | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Handle destruction of a message queue. Implementations must not | ||
390 | * free @a mq, but should take care of @a impl_state. | ||
391 | * | ||
392 | * @param mq the message queue to destroy | ||
393 | * @param impl_state state of the implementation | ||
394 | */ | ||
395 | static void | ||
396 | cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) | ||
397 | { | ||
398 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
399 | |||
400 | GNUNET_assert (mq == ch->mq); | ||
401 | ch->mq = NULL; | ||
402 | } | ||
403 | |||
404 | |||
405 | /** | ||
406 | * We had an error processing a message we forwarded from a peer to | ||
407 | * the CADET service. We should just complain about it but otherwise | ||
408 | * continue processing. | ||
409 | * | ||
410 | * @param cls closure with our `struct GNUNET_CADET_Channel` | ||
411 | * @param error error code | ||
412 | */ | ||
413 | static void | ||
414 | cadet_mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
415 | { | ||
416 | struct GNUNET_CADET_Channel *ch = cls; | ||
417 | |||
418 | if (GNUNET_MQ_ERROR_NO_MATCH == error) | ||
419 | { | ||
420 | /* Got a message we did not understand, still try to continue! */ | ||
421 | GNUNET_break_op (0); | ||
422 | GNUNET_CADET_receive_done (ch); | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
427 | "MQ error in communication with CADET: %d\n", | ||
428 | error); | ||
429 | if (NULL != ch->disconnects) | ||
430 | ch->disconnects (ch->ctx, ch); | ||
431 | GNUNET_CADET_channel_destroy (ch); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Implementation function that cancels the currently sent message. | ||
438 | * Should basically undo whatever #mq_send_impl() did. | ||
439 | * | ||
440 | * @param mq message queue | ||
441 | * @param impl_state state specific to the implementation | ||
442 | */ | ||
443 | static void | ||
444 | cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) | ||
445 | { | ||
446 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
447 | |||
448 | (void) mq; | ||
449 | GNUNET_assert (NULL != ch->pending_env); | ||
450 | GNUNET_MQ_discard (ch->pending_env); | ||
451 | ch->pending_env = NULL; | ||
452 | if (NULL != ch->mq_cont) | ||
453 | { | ||
454 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | ||
455 | ch->mq_cont = NULL; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | |||
460 | /** | ||
461 | * Process the new channel notification and add it to the channels in the handle | ||
462 | * | ||
463 | * @param cls The cadet handle | ||
464 | * @param msg A message with the details of the new incoming channel | ||
465 | */ | ||
466 | static void | ||
467 | handle_channel_created ( | ||
468 | void *cls, | ||
469 | const struct GNUNET_CADET_LocalChannelCreateMessage *msg) | ||
470 | { | ||
471 | struct GNUNET_CADET_Handle *h = cls; | ||
472 | struct GNUNET_CADET_Channel *ch; | ||
473 | struct GNUNET_CADET_Port *port; | ||
474 | const struct GNUNET_HashCode *port_number; | ||
475 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
476 | |||
477 | ccn = msg->ccn; | ||
478 | port_number = &msg->port; | ||
479 | if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
480 | { | ||
481 | GNUNET_break (0); | ||
482 | return; | ||
483 | } | ||
484 | port = find_port (h, port_number); | ||
485 | if (NULL == port) | ||
486 | { | ||
487 | /* We could have closed the port but the service didn't know about it yet | ||
488 | * This is not an error. | ||
489 | */ | ||
490 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; | ||
491 | struct GNUNET_MQ_Envelope *env; | ||
492 | |||
493 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
494 | "No handler for incoming channel %X (on port %s, recently closed?)\n", | ||
495 | ntohl (ccn.channel_of_client), | ||
496 | GNUNET_h2s (port_number)); | ||
497 | env = | ||
498 | GNUNET_MQ_msg (d_msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
499 | d_msg->ccn = msg->ccn; | ||
500 | GNUNET_MQ_send (h->mq, env); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | ch = create_channel (h, &ccn); | ||
505 | ch->peer = msg->peer; | ||
506 | ch->incoming_port = port; | ||
507 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
508 | "Creating incoming channel %X [%s] %p\n", | ||
509 | ntohl (ccn.channel_of_client), | ||
510 | GNUNET_h2s (port_number), | ||
511 | ch); | ||
512 | |||
513 | GNUNET_assert (NULL != port->connects); | ||
514 | ch->window_changes = port->window_changes; | ||
515 | ch->disconnects = port->disconnects; | ||
516 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
517 | &cadet_mq_destroy_impl, | ||
518 | &cadet_mq_cancel_impl, | ||
519 | ch, | ||
520 | port->handlers, | ||
521 | &cadet_mq_error_handler, | ||
522 | ch); | ||
523 | ch->ctx = port->connects (port->cls, ch, &msg->peer); | ||
524 | GNUNET_MQ_set_handlers_closure (ch->mq, ch->ctx); | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Process the channel destroy notification and free associated resources | ||
530 | * | ||
531 | * @param cls The cadet handle | ||
532 | * @param msg A message with the details of the channel being destroyed | ||
533 | */ | ||
534 | static void | ||
535 | handle_channel_destroy ( | ||
536 | void *cls, | ||
537 | const struct GNUNET_CADET_LocalChannelDestroyMessage *msg) | ||
538 | { | ||
539 | struct GNUNET_CADET_Handle *h = cls; | ||
540 | struct GNUNET_CADET_Channel *ch; | ||
541 | |||
542 | ch = find_channel (h, msg->ccn); | ||
543 | if (NULL == ch) | ||
544 | { | ||
545 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
546 | "Received channel destroy for unknown channel %X from CADET service (recently close?)\n", | ||
547 | ntohl (msg->ccn.channel_of_client)); | ||
548 | return; | ||
549 | } | ||
550 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
551 | "Received channel destroy for channel %X from CADET service\n", | ||
552 | ntohl (msg->ccn.channel_of_client)); | ||
553 | destroy_channel (ch); | ||
554 | } | ||
555 | |||
556 | |||
557 | /** | ||
558 | * Check that message received from CADET service is well-formed. | ||
559 | * | ||
560 | * @param cls the `struct GNUNET_CADET_Handle` | ||
561 | * @param message the message we got | ||
562 | * @return #GNUNET_OK if the message is well-formed, | ||
563 | * #GNUNET_SYSERR otherwise | ||
564 | */ | ||
565 | static int | ||
566 | check_local_data (void *cls, const struct GNUNET_CADET_LocalData *message) | ||
567 | { | ||
568 | uint16_t size; | ||
569 | |||
570 | (void) cls; | ||
571 | size = ntohs (message->header.size); | ||
572 | if (sizeof(*message) + sizeof(struct GNUNET_MessageHeader) > size) | ||
573 | { | ||
574 | GNUNET_break (0); | ||
575 | return GNUNET_SYSERR; | ||
576 | } | ||
577 | return GNUNET_OK; | ||
578 | } | ||
579 | |||
580 | |||
581 | /** | ||
582 | * Process the incoming data packets, call appropriate handlers. | ||
583 | * | ||
584 | * @param cls The cadet handle | ||
585 | * @param message A message encapsulating the data | ||
586 | */ | ||
587 | static void | ||
588 | handle_local_data (void *cls, const struct GNUNET_CADET_LocalData *message) | ||
589 | { | ||
590 | struct GNUNET_CADET_Handle *h = cls; | ||
591 | const struct GNUNET_MessageHeader *payload; | ||
592 | struct GNUNET_CADET_Channel *ch; | ||
593 | uint16_t type; | ||
594 | int fwd; | ||
595 | |||
596 | ch = find_channel (h, message->ccn); | ||
597 | if (NULL == ch) | ||
598 | { | ||
599 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
600 | "Unknown channel %X for incoming data (recently closed?)\n", | ||
601 | ntohl (message->ccn.channel_of_client)); | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | payload = (const struct GNUNET_MessageHeader *) &message[1]; | ||
606 | type = ntohs (payload->type); | ||
607 | fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
608 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
609 | "Got a %s data on channel %s [%X] of type %u\n", | ||
610 | fwd ? "FWD" : "BWD", | ||
611 | GNUNET_i2s (&ch->peer), | ||
612 | ntohl (message->ccn.channel_of_client), | ||
613 | type); | ||
614 | GNUNET_MQ_inject_message (ch->mq, payload); | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Process a local ACK message, enabling the client to send | ||
620 | * more data to the service. | ||
621 | * | ||
622 | * @param cls Cadet handle. | ||
623 | * @param message Message itself. | ||
624 | */ | ||
625 | static void | ||
626 | handle_local_ack (void *cls, const struct GNUNET_CADET_LocalAck *message) | ||
627 | { | ||
628 | struct GNUNET_CADET_Handle *h = cls; | ||
629 | struct GNUNET_CADET_Channel *ch; | ||
630 | |||
631 | ch = find_channel (h, message->ccn); | ||
632 | if (NULL == ch) | ||
633 | { | ||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
635 | "ACK on unknown channel %X\n", | ||
636 | ntohl (message->ccn.channel_of_client)); | ||
637 | return; | ||
638 | } | ||
639 | ch->allow_send++; | ||
640 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
641 | "Got an ACK on mq channel %X (peer %s); new window size is %u!\n", | ||
642 | ntohl (ch->ccn.channel_of_client), | ||
643 | GNUNET_i2s (&ch->peer), | ||
644 | ch->allow_send); | ||
645 | if (NULL == ch->pending_env) | ||
646 | { | ||
647 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
648 | "Got an ACK on mq channel %X, allow send now %u!\n", | ||
649 | ntohl (ch->ccn.channel_of_client), | ||
650 | ch->allow_send); | ||
651 | notify_window_size (ch); | ||
652 | return; | ||
653 | } | ||
654 | if (NULL != ch->mq_cont) | ||
655 | return; /* already working on it! */ | ||
656 | ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch); | ||
657 | } | ||
658 | |||
659 | |||
660 | /** | ||
661 | * Function called during #GNUNET_CADET_disconnect() to destroy | ||
662 | * all channels that are still open. | ||
663 | * | ||
664 | * @param cls the `struct GNUNET_CADET_Handle` | ||
665 | * @param cid chanenl ID | ||
666 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
667 | * @return #GNUNET_OK (continue to iterate) | ||
668 | */ | ||
669 | static int | ||
670 | destroy_channel_cb (void *cls, uint32_t cid, void *value) | ||
671 | { | ||
672 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
673 | struct GNUNET_CADET_Channel *ch = value; | ||
674 | |||
675 | (void) cls; | ||
676 | (void) cid; | ||
677 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
678 | "Destroying channel due to GNUNET_CADET_disconnect()\n"); | ||
679 | destroy_channel (ch); | ||
680 | return GNUNET_OK; | ||
681 | } | ||
682 | |||
683 | |||
684 | /** | ||
685 | * Generic error handler, called with the appropriate error code and | ||
686 | * the same closure specified at the creation of the message queue. | ||
687 | * Not every message queue implementation supports an error handler. | ||
688 | * | ||
689 | * @param cls closure, a `struct GNUNET_CORE_Handle *` | ||
690 | * @param error error code | ||
691 | */ | ||
692 | static void | ||
693 | handle_mq_error (void *cls, enum GNUNET_MQ_Error error) | ||
694 | { | ||
695 | struct GNUNET_CADET_Handle *h = cls; | ||
696 | |||
697 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); | ||
698 | GNUNET_CONTAINER_multihashmap32_iterate (h->channels, &destroy_channel_cb, h); | ||
699 | GNUNET_MQ_destroy (h->mq); | ||
700 | h->mq = NULL; | ||
701 | GNUNET_assert (NULL == h->reconnect_task); | ||
702 | h->reconnect_task = | ||
703 | GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h); | ||
704 | } | ||
705 | |||
706 | |||
707 | /** | ||
708 | * Reconnect to the service, retransmit all information to try to restore the | ||
709 | * original state. | ||
710 | * | ||
711 | * @param h handle to the cadet | ||
712 | */ | ||
713 | static void | ||
714 | reconnect (struct GNUNET_CADET_Handle *h) | ||
715 | { | ||
716 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
717 | { GNUNET_MQ_hd_fixed_size (channel_created, | ||
718 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
719 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
720 | h), | ||
721 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
722 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
723 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
724 | h), | ||
725 | GNUNET_MQ_hd_var_size (local_data, | ||
726 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
727 | struct GNUNET_CADET_LocalData, | ||
728 | h), | ||
729 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
730 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
731 | struct GNUNET_CADET_LocalAck, | ||
732 | h), | ||
733 | GNUNET_MQ_handler_end () }; | ||
734 | |||
735 | GNUNET_assert (NULL == h->mq); | ||
736 | h->mq = | ||
737 | GNUNET_CLIENT_connect (h->cfg, "cadet", handlers, &handle_mq_error, h); | ||
738 | } | ||
739 | |||
740 | |||
741 | /** | ||
742 | * Function called during #GNUNET_CADET_disconnect() to destroy | ||
743 | * all ports that are still open. | ||
744 | * | ||
745 | * @param cls the `struct GNUNET_CADET_Handle` | ||
746 | * @param id port ID | ||
747 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
748 | * @return #GNUNET_OK (continue to iterate) | ||
749 | */ | ||
750 | static int | ||
751 | destroy_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value) | ||
752 | { | ||
753 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
754 | struct GNUNET_CADET_Port *port = value; | ||
755 | |||
756 | (void) cls; | ||
757 | (void) id; | ||
758 | /* This is a warning, the app should have cleanly closed all open ports */ | ||
759 | GNUNET_break (0); | ||
760 | GNUNET_CADET_close_port (port); | ||
761 | return GNUNET_OK; | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Disconnect from the cadet service. All channels will be destroyed. All channel | ||
767 | * disconnect callbacks will be called on any still connected peers, notifying | ||
768 | * about their disconnection. The registered inbound channel cleaner will be | ||
769 | * called should any inbound channels still exist. | ||
770 | * | ||
771 | * @param handle connection to cadet to disconnect | ||
772 | */ | ||
773 | void | ||
774 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | ||
775 | { | ||
776 | GNUNET_CONTAINER_multihashmap_iterate (handle->ports, | ||
777 | &destroy_port_cb, | ||
778 | handle); | ||
779 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | ||
780 | handle->ports = NULL; | ||
781 | GNUNET_CONTAINER_multihashmap32_iterate (handle->channels, | ||
782 | &destroy_channel_cb, | ||
783 | handle); | ||
784 | GNUNET_CONTAINER_multihashmap32_destroy (handle->channels); | ||
785 | handle->channels = NULL; | ||
786 | if (NULL != handle->mq) | ||
787 | { | ||
788 | GNUNET_MQ_destroy (handle->mq); | ||
789 | handle->mq = NULL; | ||
790 | } | ||
791 | if (NULL != handle->reconnect_task) | ||
792 | { | ||
793 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
794 | handle->reconnect_task = NULL; | ||
795 | } | ||
796 | GNUNET_free (handle); | ||
797 | } | ||
798 | |||
799 | |||
800 | void | ||
801 | GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p) | ||
802 | { | ||
803 | GNUNET_assert ( | ||
804 | GNUNET_YES == | ||
805 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, &p->id, p)); | ||
806 | if (NULL != p->cadet->mq) | ||
807 | { | ||
808 | struct GNUNET_CADET_PortMessage *msg; | ||
809 | struct GNUNET_MQ_Envelope *env; | ||
810 | |||
811 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | ||
812 | msg->port = p->id; | ||
813 | GNUNET_MQ_send (p->cadet->mq, env); | ||
814 | } | ||
815 | GNUNET_free (p->handlers); | ||
816 | GNUNET_free (p); | ||
817 | } | ||
818 | |||
819 | |||
820 | /** | ||
821 | * Destroy an existing channel. | ||
822 | * | ||
823 | * The existing end callback for the channel will NOT be called. | ||
824 | * Any pending outgoing messages will be sent but no incoming messages will be | ||
825 | * accepted and no data callbacks will be called. | ||
826 | * | ||
827 | * @param channel Channel handle, becomes invalid after this call. | ||
828 | */ | ||
829 | void | ||
830 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | ||
831 | { | ||
832 | struct GNUNET_CADET_Handle *h = channel->cadet; | ||
833 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | ||
834 | struct GNUNET_MQ_Envelope *env; | ||
835 | |||
836 | if (NULL != h->mq) | ||
837 | { | ||
838 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
839 | msg->ccn = channel->ccn; | ||
840 | GNUNET_MQ_send (h->mq, env); | ||
841 | } | ||
842 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
843 | "Destroying channel due to GNUNET_CADET_channel_destroy()\n"); | ||
844 | channel->disconnects = NULL; | ||
845 | destroy_channel (channel); | ||
846 | } | ||
847 | |||
848 | |||
849 | const union GNUNET_CADET_ChannelInfo * | ||
850 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | ||
851 | enum GNUNET_CADET_ChannelInfoOption option, | ||
852 | ...) | ||
853 | { | ||
854 | switch (option) | ||
855 | { | ||
856 | case GNUNET_CADET_OPTION_PEER: | ||
857 | return (const union GNUNET_CADET_ChannelInfo *) &channel->peer; | ||
858 | |||
859 | default: | ||
860 | GNUNET_break (0); | ||
861 | return NULL; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | |||
866 | /** | ||
867 | * Send an ack on the channel to confirm the processing of a message. | ||
868 | * | ||
869 | * @param ch Channel on which to send the ACK. | ||
870 | */ | ||
871 | void | ||
872 | GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | ||
873 | { | ||
874 | struct GNUNET_CADET_LocalAck *msg; | ||
875 | struct GNUNET_MQ_Envelope *env; | ||
876 | |||
877 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
878 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
879 | "Sending ACK on channel %X\n", | ||
880 | ntohl (channel->ccn.channel_of_client)); | ||
881 | msg->ccn = channel->ccn; | ||
882 | GNUNET_MQ_send (channel->cadet->mq, env); | ||
883 | } | ||
884 | |||
885 | |||
886 | /** | ||
887 | * Connect to the MQ-based cadet service. | ||
888 | * | ||
889 | * @param cfg Configuration to use. | ||
890 | * | ||
891 | * @return Handle to the cadet service NULL on error. | ||
892 | */ | ||
893 | struct GNUNET_CADET_Handle * | ||
894 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
895 | { | ||
896 | struct GNUNET_CADET_Handle *h; | ||
897 | |||
898 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n"); | ||
899 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
900 | h->cfg = cfg; | ||
901 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES); | ||
902 | h->channels = GNUNET_CONTAINER_multihashmap32_create (4); | ||
903 | reconnect (h); | ||
904 | if (NULL == h->mq) | ||
905 | { | ||
906 | GNUNET_break (0); | ||
907 | GNUNET_CADET_disconnect (h); | ||
908 | return NULL; | ||
909 | } | ||
910 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
911 | return h; | ||
912 | } | ||
913 | |||
914 | |||
915 | /** | ||
916 | * Function to return link to AGPL source upon request. | ||
917 | * | ||
918 | * @param cls closure with the identification of the client | ||
919 | * @param msg AGPL request | ||
920 | */ | ||
921 | static void | ||
922 | return_agpl (void *cls, const struct GNUNET_MessageHeader *msg) | ||
923 | { | ||
924 | struct GNUNET_SERVICE_Client *client = cls; | ||
925 | struct GNUNET_MQ_Handle *mq; | ||
926 | struct GNUNET_MQ_Envelope *env; | ||
927 | struct GNUNET_MessageHeader *res; | ||
928 | size_t slen; | ||
929 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); | ||
930 | |||
931 | (void) msg; | ||
932 | slen = strlen (pd->agpl_url) + 1; | ||
933 | env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen); | ||
934 | memcpy (&res[1], GNUNET_AGPL_URL, slen); | ||
935 | mq = GNUNET_SERVICE_client_get_mq (client); | ||
936 | GNUNET_MQ_send (mq, env); | ||
937 | GNUNET_SERVICE_client_continue (client); | ||
938 | } | ||
939 | |||
940 | |||
941 | /** | ||
942 | * Open a port to receive incoming MQ-based channels. | ||
943 | * | ||
944 | * @param h CADET handle. | ||
945 | * @param port Hash identifying the port. | ||
946 | * @param connects Function called when an incoming channel is connected. | ||
947 | * @param connects_cls Closure for the @a connects handler. | ||
948 | * @param window_changes Function called when the transmit window size changes. | ||
949 | * @param disconnects Function called when a channel is disconnected. | ||
950 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
951 | * @return Port handle, NULL if port is in use | ||
952 | */ | ||
953 | struct GNUNET_CADET_Port * | ||
954 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, | ||
955 | const struct GNUNET_HashCode *port, | ||
956 | GNUNET_CADET_ConnectEventHandler connects, | ||
957 | void *connects_cls, | ||
958 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
959 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
960 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
961 | { | ||
962 | struct GNUNET_CADET_Port *p; | ||
963 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); | ||
964 | |||
965 | GNUNET_assert (NULL != connects); | ||
966 | GNUNET_assert (NULL != disconnects); | ||
967 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
968 | "Listening to CADET port %s\n", | ||
969 | GNUNET_h2s (port)); | ||
970 | |||
971 | p = GNUNET_new (struct GNUNET_CADET_Port); | ||
972 | p->cadet = h; | ||
973 | p->id = *port; | ||
974 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( | ||
975 | h->ports, | ||
976 | &p->id, | ||
977 | p, | ||
978 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
979 | { | ||
980 | GNUNET_free (p); | ||
981 | return NULL; | ||
982 | } | ||
983 | p->connects = connects; | ||
984 | p->cls = connects_cls; | ||
985 | p->window_changes = window_changes; | ||
986 | p->disconnects = disconnects; | ||
987 | p->handlers = (NULL == pd->agpl_url) | ||
988 | ? GNUNET_MQ_copy_handlers (handlers) | ||
989 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); | ||
990 | |||
991 | GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p)); | ||
992 | return p; | ||
993 | } | ||
994 | |||
995 | |||
996 | /** | ||
997 | * Create a new channel towards a remote peer. | ||
998 | * | ||
999 | * If the destination peer closes the channel after accepting it, | ||
1000 | * @a disconnects will be called for this channel (unless | ||
1001 | * #GNUNET_CADET_channel_destroy() was called on this end first). | ||
1002 | * | ||
1003 | * @param h CADET handle. | ||
1004 | * @param channel_cls Closure for the channel. It's given to: | ||
1005 | * - The disconnect handler @a disconnects | ||
1006 | * - Each message type callback in @a handlers | ||
1007 | * @param destination Peer identity the channel should go to. | ||
1008 | * @param port Identification of the destination port. | ||
1009 | * @param window_changes Function called when the transmit window size changes. | ||
1010 | * @param disconnects Function called when the channel is disconnected. | ||
1011 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1012 | * @return Handle to the channel. | ||
1013 | */ | ||
1014 | struct GNUNET_CADET_Channel * | ||
1015 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, | ||
1016 | void *channel_cls, | ||
1017 | const struct GNUNET_PeerIdentity *destination, | ||
1018 | const struct GNUNET_HashCode *port, | ||
1019 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1020 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1021 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
1022 | { | ||
1023 | struct GNUNET_CADET_Channel *ch; | ||
1024 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | ||
1025 | struct GNUNET_MQ_Envelope *env; | ||
1026 | |||
1027 | GNUNET_assert (NULL != disconnects); | ||
1028 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1029 | "Creating channel to peer %s at port %s\n", | ||
1030 | GNUNET_i2s (destination), | ||
1031 | GNUNET_h2s (port)); | ||
1032 | ch = create_channel (h, NULL); | ||
1033 | ch->ctx = channel_cls; | ||
1034 | ch->peer = *destination; | ||
1035 | ch->window_changes = window_changes; | ||
1036 | ch->disconnects = disconnects; | ||
1037 | |||
1038 | /* Create MQ for channel */ | ||
1039 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
1040 | &cadet_mq_destroy_impl, | ||
1041 | &cadet_mq_cancel_impl, | ||
1042 | ch, | ||
1043 | handlers, | ||
1044 | &cadet_mq_error_handler, | ||
1045 | ch); | ||
1046 | GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls); | ||
1047 | |||
1048 | /* Request channel creation to service */ | ||
1049 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1050 | msg->ccn = ch->ccn; | ||
1051 | msg->port = *port; | ||
1052 | msg->peer = *destination; | ||
1053 | GNUNET_MQ_send (h->mq, env); | ||
1054 | return ch; | ||
1055 | } | ||
1056 | |||
1057 | |||
1058 | /** | ||
1059 | * Obtain the message queue for a connected peer. | ||
1060 | * | ||
1061 | * @param channel The channel handle from which to get the MQ. | ||
1062 | * | ||
1063 | * @return NULL if @a channel is not yet connected. | ||
1064 | */ | ||
1065 | struct GNUNET_MQ_Handle * | ||
1066 | GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) | ||
1067 | { | ||
1068 | return channel->mq; | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | /* end of cadet_api.c */ | ||
diff --git a/src/service/cadet/cadet_api_drop_message.c b/src/service/cadet/cadet_api_drop_message.c new file mode 100644 index 000000000..e172418c4 --- /dev/null +++ b/src/service/cadet/cadet_api_drop_message.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_drop_message.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author t3sserakt | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "cadet.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Drop the next cadet message of a given type. | ||
31 | * | ||
32 | * @param mq message queue | ||
33 | * @param ccn client channel number. | ||
34 | * @param type of cadet message to be dropped. | ||
35 | */ | ||
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/service/cadet/cadet_api_get_channel.c b/src/service/cadet/cadet_api_get_channel.c new file mode 100644 index 000000000..05e2a8383 --- /dev/null +++ b/src/service/cadet/cadet_api_get_channel.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_get_channel.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Operation handle. | ||
36 | */ | ||
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/service/cadet/cadet_api_get_path.c b/src/service/cadet/cadet_api_get_path.c new file mode 100644 index 000000000..f32a5e20b --- /dev/null +++ b/src/service/cadet/cadet_api_get_path.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_get_path.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Operation handle. | ||
36 | */ | ||
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 | struct GNUNET_CADET_GetPath * | ||
220 | GNUNET_CADET_get_path (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
221 | const struct GNUNET_PeerIdentity *id, | ||
222 | GNUNET_CADET_PathCB callback, | ||
223 | void *callback_cls) | ||
224 | { | ||
225 | struct GNUNET_CADET_GetPath *gp; | ||
226 | |||
227 | if (NULL == callback) | ||
228 | { | ||
229 | GNUNET_break (0); | ||
230 | return NULL; | ||
231 | } | ||
232 | gp = GNUNET_new (struct GNUNET_CADET_GetPath); | ||
233 | gp->path_cb = callback; | ||
234 | gp->path_cb_cls = callback_cls; | ||
235 | gp->cfg = cfg; | ||
236 | gp->id = *id; | ||
237 | reconnect (gp); | ||
238 | if (NULL == gp->mq) | ||
239 | { | ||
240 | GNUNET_free (gp); | ||
241 | return NULL; | ||
242 | } | ||
243 | return gp; | ||
244 | } | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Cancel @a gp operation. | ||
249 | * | ||
250 | * @param gp operation to cancel | ||
251 | * @return closure from #GNUNET_CADET_get_path(). | ||
252 | */ | ||
253 | void * | ||
254 | GNUNET_CADET_get_path_cancel (struct GNUNET_CADET_GetPath *gp) | ||
255 | { | ||
256 | void *ret = gp->path_cb_cls; | ||
257 | |||
258 | if (NULL != gp->mq) | ||
259 | GNUNET_MQ_destroy (gp->mq); | ||
260 | if (NULL != gp->reconnect_task) | ||
261 | GNUNET_SCHEDULER_cancel (gp->reconnect_task); | ||
262 | GNUNET_free (gp); | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | |||
267 | /* end of cadet_api_get_path.c */ | ||
diff --git a/src/service/cadet/cadet_api_helper.c b/src/service/cadet/cadet_api_helper.c new file mode 100644 index 000000000..52aec6cc9 --- /dev/null +++ b/src/service/cadet/cadet_api_helper.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_helper.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Transitional function to convert an unsigned int port to a hash value. | ||
36 | * WARNING: local static value returned, NOT reentrant! | ||
37 | * WARNING: do not use this function for new code! | ||
38 | * | ||
39 | * @param port Numerical port (unsigned int format). | ||
40 | * | ||
41 | * @return A GNUNET_HashCode usable for the new CADET API. | ||
42 | */ | ||
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/service/cadet/cadet_api_list_peers.c b/src/service/cadet/cadet_api_list_peers.c new file mode 100644 index 000000000..52f59cc74 --- /dev/null +++ b/src/service/cadet/cadet_api_list_peers.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_list_peers.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Operation handle. | ||
36 | */ | ||
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/service/cadet/cadet_api_list_tunnels.c b/src/service/cadet/cadet_api_list_tunnels.c new file mode 100644 index 000000000..dce12835f --- /dev/null +++ b/src/service/cadet/cadet_api_list_tunnels.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_list_tunnels.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Operation handle. | ||
36 | */ | ||
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 msg 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/service/cadet/cadet_protocol.h b/src/service/cadet/cadet_protocol.h new file mode 100644 index 000000000..117a7922e --- /dev/null +++ b/src/service/cadet/cadet_protocol.h | |||
@@ -0,0 +1,541 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2007 - 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_protocol.h | ||
23 | * @brief P2P messages used by CADET | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | |||
28 | #ifndef CADET_PROTOCOL_H_ | ||
29 | #define CADET_PROTOCOL_H_ | ||
30 | |||
31 | /** | ||
32 | * At best, enable when debugging #5328! | ||
33 | */ | ||
34 | #define DEBUG_KX 0 | ||
35 | #if DEBUG_KX | ||
36 | #warning NEVER run this in production! KX debugging is on! | ||
37 | #endif | ||
38 | |||
39 | #include "platform.h" | ||
40 | #include "gnunet_util_lib.h" | ||
41 | #include "cadet.h" | ||
42 | |||
43 | #ifdef __cplusplus | ||
44 | |||
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/service/cadet/desirability_table.c b/src/service/cadet/desirability_table.c new file mode 100644 index 000000000..b4db7c2dd --- /dev/null +++ b/src/service/cadet/desirability_table.c | |||
@@ -0,0 +1,34 @@ | |||
1 | /* This file is in the public domain. */ | ||
2 | |||
3 | /** | ||
4 | * @brief Program to simulate results from #GCP_get_desirability_of_path() | ||
5 | * for various plausible inputs. | ||
6 | * @author Christian Grothoff | ||
7 | */ | ||
8 | #include "platform.h" | ||
9 | #include <stdio.h> | ||
10 | |||
11 | int | ||
12 | main () | ||
13 | { | ||
14 | for (unsigned int num_alts = 1; num_alts < 10; num_alts++) | ||
15 | for (unsigned int off = 0; off < 10; off++) | ||
16 | for (double delta = -(int) off; delta <= 5; delta += 0.25) | ||
17 | { | ||
18 | double weight_alts; | ||
19 | |||
20 | if (delta <= -1.0) | ||
21 | weight_alts = -1.0 * num_alts / delta; /* discount alternative paths */ | ||
22 | else if (delta >= 1.0) | ||
23 | weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */ | ||
24 | else | ||
25 | weight_alts = 1.0 * num_alts; /* count alternative paths normally */ | ||
26 | |||
27 | fprintf (stderr, | ||
28 | "Paths: %u Offset: %u Delta: %5.2f SCORE: %f\n", | ||
29 | num_alts, | ||
30 | off, | ||
31 | delta, | ||
32 | ((off + 1.0) / (weight_alts * weight_alts))); | ||
33 | } | ||
34 | } | ||
diff --git a/src/service/cadet/gnunet-service-cadet.c b/src/service/cadet/gnunet-service-cadet.c new file mode 100644 index 000000000..620e43cc8 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet.c | |||
@@ -0,0 +1,1376 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet.c | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * Dictionary: | ||
28 | * - peer: other cadet instance. If there is direct connection it's a neighbor. | ||
29 | * - path: series of directly connected peer from one peer to another. | ||
30 | * - connection: path which is being used in a tunnel. | ||
31 | * - tunnel: encrypted connection to a peer, neighbor or not. | ||
32 | * - channel: logical link between two clients, on the same or different peers. | ||
33 | * have properties like reliability. | ||
34 | */ | ||
35 | #include "platform.h" | ||
36 | #include "gnunet_util_lib.h" | ||
37 | #include "cadet.h" | ||
38 | #include "gnunet_statistics_service.h" | ||
39 | #include "gnunet_transport_application_service.h" | ||
40 | #include "gnunet-service-cadet.h" | ||
41 | #include "gnunet-service-cadet_channel.h" | ||
42 | #include "gnunet-service-cadet_connection.h" | ||
43 | #include "gnunet-service-cadet_core.h" | ||
44 | #include "gnunet-service-cadet_dht.h" | ||
45 | #include "gnunet-service-cadet_hello.h" | ||
46 | #include "gnunet-service-cadet_tunnels.h" | ||
47 | #include "gnunet-service-cadet_peer.h" | ||
48 | #include "gnunet-service-cadet_paths.h" | ||
49 | #include "gnunet_constants.h" | ||
50 | |||
51 | |||
52 | #define LOG(level, ...) GNUNET_log (level, __VA_ARGS__) | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Struct containing information about a client of the service | ||
57 | */ | ||
58 | struct CadetClient | ||
59 | { | ||
60 | /** | ||
61 | * Linked list next | ||
62 | */ | ||
63 | struct CadetClient *next; | ||
64 | |||
65 | /** | ||
66 | * Linked list prev | ||
67 | */ | ||
68 | struct CadetClient *prev; | ||
69 | |||
70 | /** | ||
71 | * Tunnels that belong to this client, indexed by local id, | ||
72 | * value is a `struct CadetChannel`. | ||
73 | */ | ||
74 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; | ||
75 | |||
76 | /** | ||
77 | * Handle to communicate with the client | ||
78 | */ | ||
79 | struct GNUNET_MQ_Handle *mq; | ||
80 | |||
81 | /** | ||
82 | * Client handle. | ||
83 | */ | ||
84 | struct GNUNET_SERVICE_Client *client; | ||
85 | |||
86 | /** | ||
87 | * Ports that this client has declared interest in. | ||
88 | * Indexed by port, contains `struct OpenPort` | ||
89 | */ | ||
90 | struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
91 | |||
92 | /** | ||
93 | * Channel ID to use for the next incoming channel for this client. | ||
94 | * Wraps around (in theory). | ||
95 | */ | ||
96 | struct GNUNET_CADET_ClientChannelNumber next_ccn; | ||
97 | |||
98 | /** | ||
99 | * ID of the client, mainly for debug messages. Purely internal to this file. | ||
100 | */ | ||
101 | unsigned int id; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /******************************************************************************/ | ||
106 | /*********************** GLOBAL VARIABLES ****************************/ | ||
107 | /******************************************************************************/ | ||
108 | |||
109 | /****************************** Global variables ******************************/ | ||
110 | |||
111 | /** | ||
112 | * Handle to our configuration. | ||
113 | */ | ||
114 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
115 | |||
116 | /** | ||
117 | * Handle to the statistics service. | ||
118 | */ | ||
119 | struct GNUNET_STATISTICS_Handle *stats; | ||
120 | |||
121 | /** | ||
122 | * Handle to Transport service. | ||
123 | */ | ||
124 | struct GNUNET_TRANSPORT_ApplicationHandle *transport; | ||
125 | |||
126 | /** | ||
127 | * Local peer own ID. | ||
128 | */ | ||
129 | struct GNUNET_PeerIdentity my_full_id; | ||
130 | |||
131 | /** | ||
132 | * Own private key. | ||
133 | */ | ||
134 | struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
135 | |||
136 | /** | ||
137 | * Signal that shutdown is happening: prevent recovery measures. | ||
138 | */ | ||
139 | int shutting_down; | ||
140 | |||
141 | /** | ||
142 | * DLL with all the clients, head. | ||
143 | */ | ||
144 | static struct CadetClient *clients_head; | ||
145 | |||
146 | /** | ||
147 | * DLL with all the clients, tail. | ||
148 | */ | ||
149 | static struct CadetClient *clients_tail; | ||
150 | |||
151 | /** | ||
152 | * Next ID to assign to a client. | ||
153 | */ | ||
154 | static unsigned int next_client_id; | ||
155 | |||
156 | /** | ||
157 | * All ports clients of this peer have opened. Maps from | ||
158 | * a hashed port to a `struct OpenPort`. | ||
159 | */ | ||
160 | struct GNUNET_CONTAINER_MultiHashMap *open_ports; | ||
161 | |||
162 | /** | ||
163 | * Map from ports to channels where the ports were closed at the | ||
164 | * time we got the inbound connection. | ||
165 | * Indexed by h_port, contains `struct CadetChannel`. | ||
166 | */ | ||
167 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
168 | |||
169 | /** | ||
170 | * Map from PIDs to `struct CadetPeer` entries. | ||
171 | */ | ||
172 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
173 | |||
174 | /** | ||
175 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
176 | * hash codes to `struct CadetConnection` objects. | ||
177 | */ | ||
178 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
179 | |||
180 | /** | ||
181 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
182 | */ | ||
183 | unsigned long long ratchet_messages; | ||
184 | |||
185 | /** | ||
186 | * How long until we trigger a ratched advance due to time. | ||
187 | */ | ||
188 | struct GNUNET_TIME_Relative ratchet_time; | ||
189 | |||
190 | /** | ||
191 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
192 | */ | ||
193 | struct GNUNET_TIME_Relative keepalive_period; | ||
194 | |||
195 | /** | ||
196 | * Set to non-zero values to create random drops to test retransmissions. | ||
197 | */ | ||
198 | unsigned long long drop_percent; | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Send a message to a client. | ||
203 | * | ||
204 | * @param c client to get the message | ||
205 | * @param env envelope with the message | ||
206 | */ | ||
207 | void | ||
208 | GSC_send_to_client (struct CadetClient *c, | ||
209 | struct GNUNET_MQ_Envelope *env) | ||
210 | { | ||
211 | GNUNET_MQ_send (c->mq, | ||
212 | env); | ||
213 | } | ||
214 | |||
215 | |||
216 | /** | ||
217 | * Return identifier for a client as a string. | ||
218 | * | ||
219 | * @param c client to identify | ||
220 | * @return string for debugging | ||
221 | */ | ||
222 | const char * | ||
223 | GSC_2s (struct CadetClient *c) | ||
224 | { | ||
225 | static char buf[32]; | ||
226 | |||
227 | GNUNET_snprintf (buf, | ||
228 | sizeof(buf), | ||
229 | "Client(%u)", | ||
230 | c->id); | ||
231 | return buf; | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Lookup channel of client @a c by @a ccn. | ||
237 | * | ||
238 | * @param c client to look in | ||
239 | * @param ccn channel ID to look up | ||
240 | * @return NULL if no such channel exists | ||
241 | */ | ||
242 | static struct CadetChannel * | ||
243 | lookup_channel (struct CadetClient *c, | ||
244 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
245 | { | ||
246 | return GNUNET_CONTAINER_multihashmap32_get (c->channels, | ||
247 | ntohl (ccn.channel_of_client)); | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Obtain the next LID to use for incoming connections to | ||
253 | * the given client. | ||
254 | * | ||
255 | * @param c client handle | ||
256 | */ | ||
257 | static struct GNUNET_CADET_ClientChannelNumber | ||
258 | client_get_next_ccn (struct CadetClient *c) | ||
259 | { | ||
260 | struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn; | ||
261 | |||
262 | /* increment until we have a free one... */ | ||
263 | while (NULL != | ||
264 | lookup_channel (c, | ||
265 | ccn)) | ||
266 | { | ||
267 | ccn.channel_of_client | ||
268 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
269 | if (ntohl (ccn.channel_of_client) >= | ||
270 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
271 | ccn.channel_of_client = htonl (0); | ||
272 | } | ||
273 | c->next_ccn.channel_of_client | ||
274 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
275 | return ccn; | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Bind incoming channel to this client, and notify client about | ||
281 | * incoming connection. Caller is responsible for notifying the other | ||
282 | * peer about our acceptance of the channel. | ||
283 | * | ||
284 | * @param c client to bind to | ||
285 | * @param ch channel to be bound | ||
286 | * @param dest peer that establishes the connection | ||
287 | * @param port port number | ||
288 | * @param options options | ||
289 | * @return local channel number assigned to the new client | ||
290 | */ | ||
291 | struct GNUNET_CADET_ClientChannelNumber | ||
292 | GSC_bind (struct CadetClient *c, | ||
293 | struct CadetChannel *ch, | ||
294 | struct CadetPeer *dest, | ||
295 | const struct GNUNET_HashCode *port, | ||
296 | uint32_t options) | ||
297 | { | ||
298 | struct GNUNET_MQ_Envelope *env; | ||
299 | struct GNUNET_CADET_LocalChannelCreateMessage *cm; | ||
300 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
301 | |||
302 | ccn = client_get_next_ccn (c); | ||
303 | GNUNET_assert (GNUNET_YES == | ||
304 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
305 | ntohl ( | ||
306 | ccn.channel_of_client), | ||
307 | ch, | ||
308 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
309 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
310 | "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n", | ||
311 | GCCH_2s (ch), | ||
312 | GCP_2s (dest), | ||
313 | GNUNET_h2s (port), | ||
314 | (uint32_t) ntohl (options), | ||
315 | (uint32_t) ntohl (ccn.channel_of_client)); | ||
316 | /* notify local client about incoming connection! */ | ||
317 | env = GNUNET_MQ_msg (cm, | ||
318 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
319 | cm->ccn = ccn; | ||
320 | cm->port = *port; | ||
321 | cm->opt = htonl (options); | ||
322 | cm->peer = *GCP_get_id (dest); | ||
323 | GSC_send_to_client (c, | ||
324 | env); | ||
325 | return ccn; | ||
326 | } | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Callback invoked on all peers to destroy all tunnels | ||
331 | * that may still exist. | ||
332 | * | ||
333 | * @param cls NULL | ||
334 | * @param pid identify of a peer | ||
335 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
336 | * @return #GNUNET_OK (iterate over all entries) | ||
337 | */ | ||
338 | static int | ||
339 | destroy_tunnels_now (void *cls, | ||
340 | const struct GNUNET_PeerIdentity *pid, | ||
341 | void *value) | ||
342 | { | ||
343 | struct CadetPeer *cp = value; | ||
344 | struct CadetTunnel *t = GCP_get_tunnel (cp, | ||
345 | GNUNET_NO); | ||
346 | |||
347 | if (NULL != t) | ||
348 | GCT_destroy_tunnel_now (t); | ||
349 | return GNUNET_OK; | ||
350 | } | ||
351 | |||
352 | |||
353 | /** | ||
354 | * Callback invoked on all peers to destroy all tunnels | ||
355 | * that may still exist. | ||
356 | * | ||
357 | * @param cls NULL | ||
358 | * @param pid identify of a peer | ||
359 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
360 | * @return #GNUNET_OK (iterate over all entries) | ||
361 | */ | ||
362 | static int | ||
363 | destroy_paths_now (void *cls, | ||
364 | const struct GNUNET_PeerIdentity *pid, | ||
365 | void *value) | ||
366 | { | ||
367 | struct CadetPeer *cp = value; | ||
368 | |||
369 | GCP_drop_owned_paths (cp); | ||
370 | return GNUNET_OK; | ||
371 | } | ||
372 | |||
373 | |||
374 | /** | ||
375 | * Shutdown everything once the clients have disconnected. | ||
376 | */ | ||
377 | static void | ||
378 | shutdown_rest () | ||
379 | { | ||
380 | if (NULL != stats) | ||
381 | { | ||
382 | GNUNET_STATISTICS_destroy (stats, | ||
383 | GNUNET_NO); | ||
384 | stats = NULL; | ||
385 | } | ||
386 | /* Destroy tunnels. Note that all channels must be destroyed first! */ | ||
387 | GCP_iterate_all (&destroy_tunnels_now, | ||
388 | NULL); | ||
389 | /* All tunnels, channels, connections and CORE must be down before this point. */ | ||
390 | GCP_iterate_all (&destroy_paths_now, | ||
391 | NULL); | ||
392 | /* All paths, tunnels, channels, connections and CORE must be down before this point. */ | ||
393 | GCP_destroy_all_peers (); | ||
394 | if (NULL != open_ports) | ||
395 | { | ||
396 | GNUNET_CONTAINER_multihashmap_destroy (open_ports); | ||
397 | open_ports = NULL; | ||
398 | } | ||
399 | if (NULL != loose_channels) | ||
400 | { | ||
401 | GNUNET_CONTAINER_multihashmap_destroy (loose_channels); | ||
402 | loose_channels = NULL; | ||
403 | } | ||
404 | if (NULL != peers) | ||
405 | { | ||
406 | GNUNET_CONTAINER_multipeermap_destroy (peers); | ||
407 | peers = NULL; | ||
408 | } | ||
409 | if (NULL != connections) | ||
410 | { | ||
411 | GNUNET_CONTAINER_multishortmap_destroy (connections); | ||
412 | connections = NULL; | ||
413 | } | ||
414 | if (NULL != transport) | ||
415 | { | ||
416 | GNUNET_TRANSPORT_application_done (transport); | ||
417 | transport = NULL; | ||
418 | } | ||
419 | GCD_shutdown (); | ||
420 | GCH_shutdown (); | ||
421 | GNUNET_free (my_private_key); | ||
422 | my_private_key = NULL; | ||
423 | } | ||
424 | |||
425 | |||
426 | /** | ||
427 | * Task run during shutdown. | ||
428 | * | ||
429 | * @param cls unused | ||
430 | */ | ||
431 | static void | ||
432 | shutdown_task (void *cls) | ||
433 | { | ||
434 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
435 | "Shutting down\n"); | ||
436 | shutting_down = GNUNET_YES; | ||
437 | GCO_shutdown (); | ||
438 | if (NULL == clients_head) | ||
439 | shutdown_rest (); | ||
440 | } | ||
441 | |||
442 | |||
443 | /** | ||
444 | * We had a remote connection @a value to port @a h_port before | ||
445 | * client @a cls opened port @a port. Bind them now. | ||
446 | * | ||
447 | * @param cls the `struct CadetClient` | ||
448 | * @param port the hashed port | ||
449 | * @param value the `struct CadetChannel` | ||
450 | * @return #GNUNET_YES (iterate over all such channels) | ||
451 | */ | ||
452 | static int | ||
453 | bind_loose_channel (void *cls, | ||
454 | const struct GNUNET_HashCode *port, | ||
455 | void *value) | ||
456 | { | ||
457 | struct OpenPort *op = cls; | ||
458 | struct CadetChannel *ch = value; | ||
459 | |||
460 | GCCH_bind (ch, | ||
461 | op->c, | ||
462 | &op->port); | ||
463 | GNUNET_assert (GNUNET_YES == | ||
464 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
465 | &op->h_port, | ||
466 | ch)); | ||
467 | return GNUNET_YES; | ||
468 | } | ||
469 | |||
470 | |||
471 | /** | ||
472 | * Handle port open request. Creates a mapping from the | ||
473 | * port to the respective client and checks whether we have | ||
474 | * loose channels trying to bind to the port. If so, those | ||
475 | * are bound. | ||
476 | * | ||
477 | * @param cls Identification of the client. | ||
478 | * @param pmsg The actual message. | ||
479 | */ | ||
480 | static void | ||
481 | handle_port_open (void *cls, | ||
482 | const struct GNUNET_CADET_PortMessage *pmsg) | ||
483 | { | ||
484 | struct CadetClient *c = cls; | ||
485 | struct OpenPort *op; | ||
486 | |||
487 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
488 | "Open port %s requested by %s\n", | ||
489 | GNUNET_h2s (&pmsg->port), | ||
490 | GSC_2s (c)); | ||
491 | if (NULL == c->ports) | ||
492 | c->ports = GNUNET_CONTAINER_multihashmap_create (4, | ||
493 | GNUNET_NO); | ||
494 | op = GNUNET_new (struct OpenPort); | ||
495 | op->c = c; | ||
496 | op->port = pmsg->port; | ||
497 | GCCH_hash_port (&op->h_port, | ||
498 | &pmsg->port, | ||
499 | &my_full_id); | ||
500 | if (GNUNET_OK != | ||
501 | GNUNET_CONTAINER_multihashmap_put (c->ports, | ||
502 | &op->port, | ||
503 | op, | ||
504 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
505 | { | ||
506 | GNUNET_break (0); | ||
507 | GNUNET_SERVICE_client_drop (c->client); | ||
508 | return; | ||
509 | } | ||
510 | (void) GNUNET_CONTAINER_multihashmap_put (open_ports, | ||
511 | &op->h_port, | ||
512 | op, | ||
513 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
514 | GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels, | ||
515 | &op->h_port, | ||
516 | &bind_loose_channel, | ||
517 | op); | ||
518 | GNUNET_SERVICE_client_continue (c->client); | ||
519 | } | ||
520 | |||
521 | |||
522 | /** | ||
523 | * Handler for port close requests. Marks this port as closed | ||
524 | * (unless of course we have another client with the same port | ||
525 | * open). Note that existing channels accepted on the port are | ||
526 | * not affected. | ||
527 | * | ||
528 | * @param cls Identification of the client. | ||
529 | * @param pmsg The actual message. | ||
530 | */ | ||
531 | static void | ||
532 | handle_port_close (void *cls, | ||
533 | const struct GNUNET_CADET_PortMessage *pmsg) | ||
534 | { | ||
535 | struct CadetClient *c = cls; | ||
536 | struct OpenPort *op; | ||
537 | |||
538 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Closing port %s as requested by %s\n", | ||
540 | GNUNET_h2s (&pmsg->port), | ||
541 | GSC_2s (c)); | ||
542 | if (NULL == c->ports) | ||
543 | { | ||
544 | /* Client closed a port despite _never_ having opened one? */ | ||
545 | GNUNET_break (0); | ||
546 | GNUNET_SERVICE_client_drop (c->client); | ||
547 | return; | ||
548 | } | ||
549 | op = GNUNET_CONTAINER_multihashmap_get (c->ports, | ||
550 | &pmsg->port); | ||
551 | if (NULL == op) | ||
552 | { | ||
553 | GNUNET_break (0); | ||
554 | GNUNET_SERVICE_client_drop (c->client); | ||
555 | return; | ||
556 | } | ||
557 | GNUNET_assert (GNUNET_YES == | ||
558 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
559 | &op->port, | ||
560 | op)); | ||
561 | GNUNET_assert (GNUNET_YES == | ||
562 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
563 | &op->h_port, | ||
564 | op)); | ||
565 | GNUNET_free (op); | ||
566 | GNUNET_SERVICE_client_continue (c->client); | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * Handler for requests for us creating a new channel to another peer and port. | ||
572 | * | ||
573 | * @param cls Identification of the client. | ||
574 | * @param tcm The actual message. | ||
575 | */ | ||
576 | static void | ||
577 | handle_channel_create (void *cls, | ||
578 | const struct GNUNET_CADET_LocalChannelCreateMessage *tcm) | ||
579 | { | ||
580 | struct CadetClient *c = cls; | ||
581 | struct CadetChannel *ch; | ||
582 | |||
583 | if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
584 | { | ||
585 | /* Channel ID not in allowed range. */ | ||
586 | LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID not in allowed range."); | ||
587 | GNUNET_break (0); | ||
588 | GNUNET_SERVICE_client_drop (c->client); | ||
589 | return; | ||
590 | } | ||
591 | ch = lookup_channel (c, | ||
592 | tcm->ccn); | ||
593 | if (NULL != ch) | ||
594 | { | ||
595 | /* Channel ID already in use. Not allowed. */ | ||
596 | LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID already in use. Not allowed."); | ||
597 | GNUNET_break (0); | ||
598 | GNUNET_SERVICE_client_drop (c->client); | ||
599 | return; | ||
600 | } | ||
601 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
602 | "New channel to %s at port %s requested by %s\n", | ||
603 | GNUNET_i2s (&tcm->peer), | ||
604 | GNUNET_h2s (&tcm->port), | ||
605 | GSC_2s (c)); | ||
606 | |||
607 | /* Create channel */ | ||
608 | ch = GCCH_channel_local_new (c, | ||
609 | tcm->ccn, | ||
610 | GCP_get (&tcm->peer, | ||
611 | GNUNET_YES), | ||
612 | &tcm->port, | ||
613 | ntohl (tcm->opt)); | ||
614 | if (NULL == ch) | ||
615 | { | ||
616 | GNUNET_break (0); | ||
617 | GNUNET_SERVICE_client_drop (c->client); | ||
618 | return; | ||
619 | } | ||
620 | GNUNET_assert (GNUNET_YES == | ||
621 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
622 | ntohl ( | ||
623 | tcm->ccn. | ||
624 | channel_of_client), | ||
625 | ch, | ||
626 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
627 | |||
628 | GNUNET_SERVICE_client_continue (c->client); | ||
629 | } | ||
630 | |||
631 | |||
632 | /** | ||
633 | * Handler for requests of destroying an existing channel. | ||
634 | * | ||
635 | * @param cls client identification of the client | ||
636 | * @param msg the actual message | ||
637 | */ | ||
638 | static void | ||
639 | handle_channel_destroy (void *cls, | ||
640 | const struct | ||
641 | GNUNET_CADET_LocalChannelDestroyMessage *msg) | ||
642 | { | ||
643 | struct CadetClient *c = cls; | ||
644 | struct CadetChannel *ch; | ||
645 | |||
646 | ch = lookup_channel (c, | ||
647 | msg->ccn); | ||
648 | if (NULL == ch) | ||
649 | { | ||
650 | /* Client attempted to destroy unknown channel. | ||
651 | Can happen if the other side went down at the same time.*/ | ||
652 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
653 | "%s tried to destroy unknown channel %X\n", | ||
654 | GSC_2s (c), | ||
655 | (uint32_t) ntohl (msg->ccn.channel_of_client)); | ||
656 | GNUNET_SERVICE_client_continue (c->client); | ||
657 | return; | ||
658 | } | ||
659 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
660 | "%s is destroying %s\n", | ||
661 | GSC_2s (c), | ||
662 | GCCH_2s (ch)); | ||
663 | GNUNET_assert (GNUNET_YES == | ||
664 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
665 | ntohl ( | ||
666 | msg->ccn. | ||
667 | channel_of_client), | ||
668 | ch)); | ||
669 | GCCH_channel_local_destroy (ch, | ||
670 | c, | ||
671 | msg->ccn); | ||
672 | GNUNET_SERVICE_client_continue (c->client); | ||
673 | } | ||
674 | |||
675 | |||
676 | /** | ||
677 | * Check for client traffic data message is well-formed. | ||
678 | * | ||
679 | * @param cls identification of the client | ||
680 | * @param msg the actual message | ||
681 | * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not | ||
682 | */ | ||
683 | static int | ||
684 | check_local_data (void *cls, | ||
685 | const struct GNUNET_CADET_LocalData *msg) | ||
686 | { | ||
687 | size_t payload_size; | ||
688 | size_t payload_claimed_size; | ||
689 | const char *buf; | ||
690 | struct GNUNET_MessageHeader pa; | ||
691 | |||
692 | /* FIXME: what is the format we shall allow for @a msg? | ||
693 | ONE payload item or multiple? Seems current cadet_api | ||
694 | at least in theory allows more than one. Next-gen | ||
695 | cadet_api will likely no more, so we could then | ||
696 | simplify this mess again. *//* Sanity check for message size */payload_size = ntohs (msg->header.size) - sizeof(*msg); | ||
697 | buf = (const char *) &msg[1]; | ||
698 | while (payload_size >= sizeof(struct GNUNET_MessageHeader)) | ||
699 | { | ||
700 | /* need to memcpy() for alignment */ | ||
701 | GNUNET_memcpy (&pa, | ||
702 | buf, | ||
703 | sizeof(pa)); | ||
704 | payload_claimed_size = ntohs (pa.size); | ||
705 | if ((payload_size < payload_claimed_size) || | ||
706 | (payload_claimed_size < sizeof(struct GNUNET_MessageHeader)) || | ||
707 | (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size)) | ||
708 | { | ||
709 | GNUNET_break (0); | ||
710 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
711 | "Local data of %u total size had sub-message %u at %u with %u bytes\n", | ||
712 | ntohs (msg->header.size), | ||
713 | ntohs (pa.type), | ||
714 | (unsigned int) (buf - (const char *) &msg[1]), | ||
715 | (unsigned int) payload_claimed_size); | ||
716 | return GNUNET_SYSERR; | ||
717 | } | ||
718 | payload_size -= payload_claimed_size; | ||
719 | buf += payload_claimed_size; | ||
720 | } | ||
721 | if (0 != payload_size) | ||
722 | { | ||
723 | GNUNET_break_op (0); | ||
724 | return GNUNET_SYSERR; | ||
725 | } | ||
726 | return GNUNET_OK; | ||
727 | } | ||
728 | |||
729 | |||
730 | /** | ||
731 | * Handler for client payload traffic to be send on a channel to | ||
732 | * another peer. | ||
733 | * | ||
734 | * @param cls identification of the client | ||
735 | * @param msg the actual message | ||
736 | */ | ||
737 | static void | ||
738 | handle_local_data (void *cls, | ||
739 | const struct GNUNET_CADET_LocalData *msg) | ||
740 | { | ||
741 | struct CadetClient *c = cls; | ||
742 | struct CadetChannel *ch; | ||
743 | size_t payload_size; | ||
744 | const char *buf; | ||
745 | |||
746 | ch = lookup_channel (c, | ||
747 | msg->ccn); | ||
748 | if (NULL == ch) | ||
749 | { | ||
750 | /* Channel does not exist (anymore) */ | ||
751 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
752 | "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n", | ||
753 | (unsigned int) ntohl (msg->ccn.channel_of_client)); | ||
754 | GNUNET_SERVICE_client_continue (c->client); | ||
755 | return; | ||
756 | } | ||
757 | payload_size = ntohs (msg->header.size) - sizeof(*msg); | ||
758 | GNUNET_STATISTICS_update (stats, | ||
759 | "# payload received from clients", | ||
760 | payload_size, | ||
761 | GNUNET_NO); | ||
762 | buf = (const char *) &msg[1]; | ||
763 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
764 | "Received %u bytes payload from %s for %s\n", | ||
765 | (unsigned int) payload_size, | ||
766 | GSC_2s (c), | ||
767 | GCCH_2s (ch)); | ||
768 | if (GNUNET_OK != | ||
769 | GCCH_handle_local_data (ch, | ||
770 | msg->ccn, | ||
771 | buf, | ||
772 | payload_size)) | ||
773 | { | ||
774 | GNUNET_break (0); | ||
775 | GNUNET_SERVICE_client_drop (c->client); | ||
776 | return; | ||
777 | } | ||
778 | GNUNET_SERVICE_client_continue (c->client); | ||
779 | } | ||
780 | |||
781 | |||
782 | /** | ||
783 | * Handler for client's ACKs for payload traffic. | ||
784 | * | ||
785 | * @param cls identification of the client. | ||
786 | * @param msg The actual message. | ||
787 | */ | ||
788 | static void | ||
789 | handle_local_ack (void *cls, | ||
790 | const struct GNUNET_CADET_LocalAck *msg) | ||
791 | { | ||
792 | struct CadetClient *c = cls; | ||
793 | struct CadetChannel *ch; | ||
794 | |||
795 | ch = lookup_channel (c, | ||
796 | msg->ccn); | ||
797 | if (NULL == ch) | ||
798 | { | ||
799 | /* Channel does not exist (anymore) */ | ||
800 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
801 | "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n", | ||
802 | (unsigned int) ntohl (msg->ccn.channel_of_client)); | ||
803 | GNUNET_SERVICE_client_continue (c->client); | ||
804 | return; | ||
805 | } | ||
806 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
807 | "Got a local ACK from %s for %s\n", | ||
808 | GSC_2s (c), | ||
809 | GCCH_2s (ch)); | ||
810 | GCCH_handle_local_ack (ch, | ||
811 | msg->ccn); | ||
812 | GNUNET_SERVICE_client_continue (c->client); | ||
813 | } | ||
814 | |||
815 | |||
816 | /** | ||
817 | * Iterator over all peers to send a monitoring client info about each peer. | ||
818 | * | ||
819 | * @param cls Closure (). | ||
820 | * @param peer Peer ID (tunnel remote peer). | ||
821 | * @param value Peer info. | ||
822 | * @return #GNUNET_YES, to keep iterating. | ||
823 | */ | ||
824 | static int | ||
825 | get_all_peers_iterator (void *cls, | ||
826 | const struct GNUNET_PeerIdentity *peer, | ||
827 | void *value) | ||
828 | { | ||
829 | struct CadetClient *c = cls; | ||
830 | struct CadetPeer *p = value; | ||
831 | struct GNUNET_MQ_Envelope *env; | ||
832 | struct GNUNET_CADET_LocalInfoPeers *msg; | ||
833 | |||
834 | env = GNUNET_MQ_msg (msg, | ||
835 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
836 | msg->destination = *peer; | ||
837 | msg->paths = htons (GCP_count_paths (p)); | ||
838 | msg->tunnel = htons (NULL != GCP_get_tunnel (p, | ||
839 | GNUNET_NO)); | ||
840 | msg->best_path_length = htonl (0); // FIXME: get length of shortest known path! | ||
841 | GNUNET_MQ_send (c->mq, | ||
842 | env); | ||
843 | return GNUNET_YES; | ||
844 | } | ||
845 | |||
846 | |||
847 | /** | ||
848 | * Handler for client's INFO PEERS request. | ||
849 | * | ||
850 | * @param cls Identification of the client. | ||
851 | * @param message The actual message. | ||
852 | */ | ||
853 | static void | ||
854 | handle_get_peers (void *cls, | ||
855 | const struct GNUNET_MessageHeader *message) | ||
856 | { | ||
857 | struct CadetClient *c = cls; | ||
858 | struct GNUNET_MQ_Envelope *env; | ||
859 | struct GNUNET_MessageHeader *reply; | ||
860 | |||
861 | GCP_iterate_all (&get_all_peers_iterator, | ||
862 | c); | ||
863 | env = GNUNET_MQ_msg (reply, | ||
864 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END); | ||
865 | GNUNET_MQ_send (c->mq, | ||
866 | env); | ||
867 | GNUNET_SERVICE_client_continue (c->client); | ||
868 | } | ||
869 | |||
870 | |||
871 | /** | ||
872 | * Iterator over all paths of a peer to build an InfoPeer message. | ||
873 | * Message contains blocks of peers, first not included. | ||
874 | * | ||
875 | * @param cls message queue for transmission | ||
876 | * @param path Path itself | ||
877 | * @param off offset of the peer on @a path | ||
878 | * @return #GNUNET_YES if should keep iterating. | ||
879 | * #GNUNET_NO otherwise. | ||
880 | */ | ||
881 | static int | ||
882 | path_info_iterator (void *cls, | ||
883 | struct CadetPeerPath *path, | ||
884 | unsigned int off) | ||
885 | { | ||
886 | struct GNUNET_MQ_Handle *mq = cls; | ||
887 | struct GNUNET_MQ_Envelope *env; | ||
888 | struct GNUNET_CADET_LocalInfoPath *resp; | ||
889 | struct GNUNET_PeerIdentity *id; | ||
890 | size_t path_size; | ||
891 | unsigned int path_length; | ||
892 | |||
893 | path_length = GCPP_get_length (path); | ||
894 | path_size = sizeof(struct GNUNET_PeerIdentity) * path_length; | ||
895 | if (sizeof(*resp) + path_size > UINT16_MAX) | ||
896 | { | ||
897 | /* try just giving the relevant path */ | ||
898 | path_length = GNUNET_MIN ((UINT16_MAX - sizeof(*resp)) / sizeof(struct | ||
899 | GNUNET_PeerIdentity), | ||
900 | off); | ||
901 | path_size = sizeof(struct GNUNET_PeerIdentity) * path_length; | ||
902 | } | ||
903 | if (sizeof(*resp) + path_size > UINT16_MAX) | ||
904 | { | ||
905 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
906 | "Path of %u entries is too long for info message\n", | ||
907 | path_length); | ||
908 | return GNUNET_YES; | ||
909 | } | ||
910 | env = GNUNET_MQ_msg_extra (resp, | ||
911 | path_size, | ||
912 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH); | ||
913 | id = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
914 | |||
915 | /* Don't copy first peer. First peer is always the local one. Last | ||
916 | * peer is always the destination (leave as 0, EOL). | ||
917 | */ | ||
918 | for (unsigned int i = 0; i < path_length; i++) | ||
919 | id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path, | ||
920 | i)); | ||
921 | resp->off = htonl (off); | ||
922 | GNUNET_MQ_send (mq, | ||
923 | env); | ||
924 | return GNUNET_YES; | ||
925 | } | ||
926 | |||
927 | |||
928 | /** | ||
929 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH request. | ||
930 | * | ||
931 | * @param cls Identification of the client. | ||
932 | * @param msg The actual message. | ||
933 | */ | ||
934 | static void | ||
935 | handle_show_path (void *cls, | ||
936 | const struct GNUNET_CADET_RequestPathInfoMessage *msg) | ||
937 | { | ||
938 | struct CadetClient *c = cls; | ||
939 | struct CadetPeer *p; | ||
940 | struct GNUNET_MQ_Envelope *env; | ||
941 | struct GNUNET_MessageHeader *resp; | ||
942 | |||
943 | p = GCP_get (&msg->peer, | ||
944 | GNUNET_NO); | ||
945 | if (NULL != p) | ||
946 | GCP_iterate_indirect_paths (p, | ||
947 | &path_info_iterator, | ||
948 | c->mq); | ||
949 | env = GNUNET_MQ_msg (resp, | ||
950 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END); | ||
951 | GNUNET_MQ_send (c->mq, | ||
952 | env); | ||
953 | GNUNET_SERVICE_client_continue (c->client); | ||
954 | } | ||
955 | |||
956 | |||
957 | /** | ||
958 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
959 | * | ||
960 | * @param cls Closure (). | ||
961 | * @param peer Peer ID (tunnel remote peer). | ||
962 | * @param value a `struct CadetPeer` | ||
963 | * @return #GNUNET_YES, to keep iterating. | ||
964 | */ | ||
965 | static int | ||
966 | get_all_tunnels_iterator (void *cls, | ||
967 | const struct GNUNET_PeerIdentity *peer, | ||
968 | void *value) | ||
969 | { | ||
970 | struct CadetClient *c = cls; | ||
971 | struct CadetPeer *p = value; | ||
972 | struct GNUNET_MQ_Envelope *env; | ||
973 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
974 | struct CadetTunnel *t; | ||
975 | |||
976 | t = GCP_get_tunnel (p, | ||
977 | GNUNET_NO); | ||
978 | if (NULL == t) | ||
979 | return GNUNET_YES; | ||
980 | env = GNUNET_MQ_msg (msg, | ||
981 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
982 | msg->destination = *peer; | ||
983 | msg->channels = htonl (GCT_count_channels (t)); | ||
984 | msg->connections = htonl (GCT_count_any_connections (t)); | ||
985 | msg->cstate = htons (0); | ||
986 | msg->estate = htons ((uint16_t) GCT_get_estate (t)); | ||
987 | GNUNET_MQ_send (c->mq, | ||
988 | env); | ||
989 | return GNUNET_YES; | ||
990 | } | ||
991 | |||
992 | |||
993 | /** | ||
994 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS request. | ||
995 | * | ||
996 | * @param cls client Identification of the client. | ||
997 | * @param message The actual message. | ||
998 | */ | ||
999 | static void | ||
1000 | handle_info_tunnels (void *cls, | ||
1001 | const struct GNUNET_MessageHeader *message) | ||
1002 | { | ||
1003 | struct CadetClient *c = cls; | ||
1004 | struct GNUNET_MQ_Envelope *env; | ||
1005 | struct GNUNET_MessageHeader *reply; | ||
1006 | |||
1007 | GCP_iterate_all (&get_all_tunnels_iterator, | ||
1008 | c); | ||
1009 | env = GNUNET_MQ_msg (reply, | ||
1010 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END); | ||
1011 | GNUNET_MQ_send (c->mq, | ||
1012 | env); | ||
1013 | GNUNET_SERVICE_client_continue (c->client); | ||
1014 | } | ||
1015 | |||
1016 | |||
1017 | /** | ||
1018 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE request. | ||
1019 | * | ||
1020 | * @param cls client Identification of the client. | ||
1021 | * @param message The actual message. | ||
1022 | */ | ||
1023 | static void | ||
1024 | handle_drop_message (void *cls, | ||
1025 | const struct GNUNET_CADET_RequestDropCadetMessage *message) | ||
1026 | { | ||
1027 | struct CadetClient *c = cls; | ||
1028 | struct CadetChannel *ch; | ||
1029 | |||
1030 | ch = lookup_channel (c, | ||
1031 | message->ccn); | ||
1032 | |||
1033 | if (NULL != ch) | ||
1034 | GCCH_assign_type_to_drop (ch, message); | ||
1035 | |||
1036 | GNUNET_SERVICE_client_continue (c->client); | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | /** | ||
1041 | * Callback called when a client connects to the service. | ||
1042 | * | ||
1043 | * @param cls closure for the service | ||
1044 | * @param client the new client that connected to the service | ||
1045 | * @param mq the message queue used to send messages to the client | ||
1046 | * @return @a c | ||
1047 | */ | ||
1048 | static void * | ||
1049 | client_connect_cb (void *cls, | ||
1050 | struct GNUNET_SERVICE_Client *client, | ||
1051 | struct GNUNET_MQ_Handle *mq) | ||
1052 | { | ||
1053 | struct CadetClient *c; | ||
1054 | |||
1055 | c = GNUNET_new (struct CadetClient); | ||
1056 | c->client = client; | ||
1057 | c->mq = mq; | ||
1058 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
1059 | c->channels | ||
1060 | = GNUNET_CONTAINER_multihashmap32_create (32); | ||
1061 | GNUNET_CONTAINER_DLL_insert (clients_head, | ||
1062 | clients_tail, | ||
1063 | c); | ||
1064 | GNUNET_STATISTICS_update (stats, | ||
1065 | "# clients", | ||
1066 | +1, | ||
1067 | GNUNET_NO); | ||
1068 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1069 | "%s connected\n", | ||
1070 | GSC_2s (c)); | ||
1071 | return c; | ||
1072 | } | ||
1073 | |||
1074 | |||
1075 | /** | ||
1076 | * A channel was destroyed by the other peer. Tell our client. | ||
1077 | * | ||
1078 | * @param c client that lost a channel | ||
1079 | * @param ccn channel identification number for the client | ||
1080 | * @param ch the channel object | ||
1081 | */ | ||
1082 | void | ||
1083 | GSC_handle_remote_channel_destroy (struct CadetClient *c, | ||
1084 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1085 | struct CadetChannel *ch) | ||
1086 | { | ||
1087 | struct GNUNET_MQ_Envelope *env; | ||
1088 | struct GNUNET_CADET_LocalChannelDestroyMessage *tdm; | ||
1089 | |||
1090 | env = GNUNET_MQ_msg (tdm, | ||
1091 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1092 | tdm->ccn = ccn; | ||
1093 | GSC_send_to_client (c, | ||
1094 | env); | ||
1095 | GNUNET_assert (GNUNET_YES == | ||
1096 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1097 | ntohl ( | ||
1098 | ccn.channel_of_client), | ||
1099 | ch)); | ||
1100 | } | ||
1101 | |||
1102 | |||
1103 | void | ||
1104 | GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port, | ||
1105 | struct CadetChannel *ch) | ||
1106 | { | ||
1107 | GNUNET_assert (GNUNET_YES == | ||
1108 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
1109 | h_port, | ||
1110 | ch)); | ||
1111 | } | ||
1112 | |||
1113 | |||
1114 | /** | ||
1115 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
1116 | * | ||
1117 | * @param cls Closure (client that has disconnected). | ||
1118 | * @param key The local channel id in host byte order | ||
1119 | * @param value The value stored at the key (channel to destroy). | ||
1120 | * @return #GNUNET_OK, keep iterating. | ||
1121 | */ | ||
1122 | static int | ||
1123 | channel_destroy_iterator (void *cls, | ||
1124 | uint32_t key, | ||
1125 | void *value) | ||
1126 | { | ||
1127 | struct CadetClient *c = cls; | ||
1128 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1129 | struct CadetChannel *ch = value; | ||
1130 | |||
1131 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1132 | "Destroying %s, due to %s disconnecting.\n", | ||
1133 | GCCH_2s (ch), | ||
1134 | GSC_2s (c)); | ||
1135 | ccn.channel_of_client = htonl (key); | ||
1136 | GNUNET_assert (GNUNET_YES == | ||
1137 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1138 | key, | ||
1139 | ch)); | ||
1140 | GCCH_channel_local_destroy (ch, | ||
1141 | c, | ||
1142 | ccn); | ||
1143 | return GNUNET_OK; | ||
1144 | } | ||
1145 | |||
1146 | |||
1147 | /** | ||
1148 | * Remove client's ports from the global hashmap on disconnect. | ||
1149 | * | ||
1150 | * @param cls the `struct CadetClient` | ||
1151 | * @param port the port. | ||
1152 | * @param value the `struct OpenPort` to remove | ||
1153 | * @return #GNUNET_OK, keep iterating. | ||
1154 | */ | ||
1155 | static int | ||
1156 | client_release_ports (void *cls, | ||
1157 | const struct GNUNET_HashCode *port, | ||
1158 | void *value) | ||
1159 | { | ||
1160 | struct CadetClient *c = cls; | ||
1161 | struct OpenPort *op = value; | ||
1162 | |||
1163 | GNUNET_assert (c == op->c); | ||
1164 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1165 | "Closing port %s due to %s disconnect.\n", | ||
1166 | GNUNET_h2s (port), | ||
1167 | GSC_2s (c)); | ||
1168 | GNUNET_assert (GNUNET_YES == | ||
1169 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
1170 | &op->h_port, | ||
1171 | op)); | ||
1172 | GNUNET_assert (GNUNET_YES == | ||
1173 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
1174 | port, | ||
1175 | op)); | ||
1176 | GNUNET_free (op); | ||
1177 | return GNUNET_OK; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /** | ||
1182 | * Callback called when a client disconnected from the service | ||
1183 | * | ||
1184 | * @param cls closure for the service | ||
1185 | * @param client the client that disconnected | ||
1186 | * @param internal_cls should be equal to @a c | ||
1187 | */ | ||
1188 | static void | ||
1189 | client_disconnect_cb (void *cls, | ||
1190 | struct GNUNET_SERVICE_Client *client, | ||
1191 | void *internal_cls) | ||
1192 | { | ||
1193 | struct CadetClient *c = internal_cls; | ||
1194 | |||
1195 | GNUNET_assert (c->client == client); | ||
1196 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1197 | "%s is disconnecting.\n", | ||
1198 | GSC_2s (c)); | ||
1199 | if (NULL != c->channels) | ||
1200 | { | ||
1201 | GNUNET_CONTAINER_multihashmap32_iterate (c->channels, | ||
1202 | &channel_destroy_iterator, | ||
1203 | c); | ||
1204 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels)); | ||
1205 | GNUNET_CONTAINER_multihashmap32_destroy (c->channels); | ||
1206 | } | ||
1207 | if (NULL != c->ports) | ||
1208 | { | ||
1209 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
1210 | &client_release_ports, | ||
1211 | c); | ||
1212 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
1213 | } | ||
1214 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
1215 | clients_tail, | ||
1216 | c); | ||
1217 | GNUNET_STATISTICS_update (stats, | ||
1218 | "# clients", | ||
1219 | -1, | ||
1220 | GNUNET_NO); | ||
1221 | GNUNET_free (c); | ||
1222 | if ((NULL == clients_head) && | ||
1223 | (GNUNET_YES == shutting_down)) | ||
1224 | shutdown_rest (); | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Setup CADET internals. | ||
1230 | * | ||
1231 | * @param cls closure | ||
1232 | * @param c configuration to use | ||
1233 | */ | ||
1234 | static void | ||
1235 | run (void *cls, | ||
1236 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1237 | struct GNUNET_SERVICE_Handle *service) | ||
1238 | { | ||
1239 | cfg = c; | ||
1240 | if (GNUNET_OK != | ||
1241 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1242 | "CADET", | ||
1243 | "RATCHET_MESSAGES", | ||
1244 | &ratchet_messages)) | ||
1245 | { | ||
1246 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1247 | "CADET", | ||
1248 | "RATCHET_MESSAGES", | ||
1249 | "needs to be a number"); | ||
1250 | ratchet_messages = 64; | ||
1251 | } | ||
1252 | if (GNUNET_OK != | ||
1253 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1254 | "CADET", | ||
1255 | "RATCHET_TIME", | ||
1256 | &ratchet_time)) | ||
1257 | { | ||
1258 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1259 | "CADET", | ||
1260 | "RATCHET_TIME", | ||
1261 | "need delay value"); | ||
1262 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1263 | } | ||
1264 | if (GNUNET_OK != | ||
1265 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1266 | "CADET", | ||
1267 | "REFRESH_CONNECTION_TIME", | ||
1268 | &keepalive_period)) | ||
1269 | { | ||
1270 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1271 | "CADET", | ||
1272 | "REFRESH_CONNECTION_TIME", | ||
1273 | "need delay value"); | ||
1274 | keepalive_period = GNUNET_TIME_UNIT_MINUTES; | ||
1275 | } | ||
1276 | if (GNUNET_OK != | ||
1277 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1278 | "CADET", | ||
1279 | "DROP_PERCENT", | ||
1280 | &drop_percent)) | ||
1281 | { | ||
1282 | drop_percent = 0; | ||
1283 | } | ||
1284 | else | ||
1285 | { | ||
1286 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1287 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1288 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1289 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1290 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1291 | } | ||
1292 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
1293 | if (NULL == my_private_key) | ||
1294 | { | ||
1295 | GNUNET_break (0); | ||
1296 | GNUNET_SCHEDULER_shutdown (); | ||
1297 | return; | ||
1298 | } | ||
1299 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | ||
1300 | &my_full_id.public_key); | ||
1301 | stats = GNUNET_STATISTICS_create ("cadet", | ||
1302 | c); | ||
1303 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1304 | NULL); | ||
1305 | transport = GNUNET_TRANSPORT_application_init (c); | ||
1306 | /* FIXME: optimize code to allow GNUNET_YES here! */ | ||
1307 | open_ports = GNUNET_CONTAINER_multihashmap_create (16, | ||
1308 | GNUNET_NO); | ||
1309 | loose_channels = GNUNET_CONTAINER_multihashmap_create (16, | ||
1310 | GNUNET_NO); | ||
1311 | peers = GNUNET_CONTAINER_multipeermap_create (16, | ||
1312 | GNUNET_YES); | ||
1313 | connections = GNUNET_CONTAINER_multishortmap_create (256, | ||
1314 | GNUNET_YES); | ||
1315 | GCH_init (c); | ||
1316 | GCD_init (c); | ||
1317 | GCO_init (c); | ||
1318 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1319 | "CADET started for peer %s\n", | ||
1320 | GNUNET_i2s (&my_full_id)); | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Define "main" method using service macro. | ||
1326 | */ | ||
1327 | GNUNET_SERVICE_MAIN | ||
1328 | ("cadet", | ||
1329 | GNUNET_SERVICE_OPTION_NONE, | ||
1330 | &run, | ||
1331 | &client_connect_cb, | ||
1332 | &client_disconnect_cb, | ||
1333 | NULL, | ||
1334 | GNUNET_MQ_hd_fixed_size (port_open, | ||
1335 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1336 | struct GNUNET_CADET_PortMessage, | ||
1337 | NULL), | ||
1338 | GNUNET_MQ_hd_fixed_size (port_close, | ||
1339 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1340 | struct GNUNET_CADET_PortMessage, | ||
1341 | NULL), | ||
1342 | GNUNET_MQ_hd_fixed_size (channel_create, | ||
1343 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1344 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1345 | NULL), | ||
1346 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1347 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1348 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1349 | NULL), | ||
1350 | GNUNET_MQ_hd_var_size (local_data, | ||
1351 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1352 | struct GNUNET_CADET_LocalData, | ||
1353 | NULL), | ||
1354 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1355 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1356 | struct GNUNET_CADET_LocalAck, | ||
1357 | NULL), | ||
1358 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1359 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS, | ||
1360 | struct GNUNET_MessageHeader, | ||
1361 | NULL), | ||
1362 | GNUNET_MQ_hd_fixed_size (show_path, | ||
1363 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH, | ||
1364 | struct GNUNET_CADET_RequestPathInfoMessage, | ||
1365 | NULL), | ||
1366 | GNUNET_MQ_hd_fixed_size (info_tunnels, | ||
1367 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS, | ||
1368 | struct GNUNET_MessageHeader, | ||
1369 | NULL), | ||
1370 | GNUNET_MQ_hd_fixed_size (drop_message, | ||
1371 | GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE, | ||
1372 | struct GNUNET_CADET_RequestDropCadetMessage, | ||
1373 | NULL), | ||
1374 | GNUNET_MQ_handler_end ()); | ||
1375 | |||
1376 | /* end of gnunet-service-cadet-new.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet.h b/src/service/cadet/gnunet-service-cadet.h new file mode 100644 index 000000000..8f2386d00 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet.h | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet.h | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_H | ||
28 | #define GNUNET_SERVICE_CADET_H | ||
29 | |||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | /** | ||
34 | * A client to the CADET service. Each client gets a unique handle. | ||
35 | */ | ||
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 Transport service. | ||
201 | */ | ||
202 | extern struct GNUNET_TRANSPORT_ApplicationHandle *transport; | ||
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/service/cadet/gnunet-service-cadet_channel.c b/src/service/cadet/gnunet-service-cadet_channel.c new file mode 100644 index 000000000..78658c296 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_channel.c | |||
@@ -0,0 +1,2008 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_channel.c | ||
22 | * @brief logical links between CADET clients | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - Congestion/flow control: | ||
28 | * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
29 | * (and figure out how/where to use this!) | ||
30 | * + figure out flow control without ACKs (unreliable traffic!) | ||
31 | * - revisit handling of 'unbuffered' traffic! | ||
32 | * (need to push down through tunnel into connection selection) | ||
33 | * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe | ||
34 | * reserve more bits in 'options' to allow for buffer size control? | ||
35 | */ | ||
36 | #include "platform.h" | ||
37 | #include "cadet.h" | ||
38 | #include "gnunet_statistics_service.h" | ||
39 | #include "gnunet-service-cadet_channel.h" | ||
40 | #include "gnunet-service-cadet_connection.h" | ||
41 | #include "gnunet-service-cadet_tunnels.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
43 | |||
44 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__) | ||
45 | |||
46 | /** | ||
47 | * How long do we initially wait before retransmitting? | ||
48 | */ | ||
49 | #define CADET_INITIAL_RETRANSMIT_TIME \ | ||
50 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
51 | |||
52 | /** | ||
53 | * How long do we wait before dropping state about incoming | ||
54 | * connection to closed port? | ||
55 | */ | ||
56 | #define TIMEOUT_CLOSED_PORT \ | ||
57 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
58 | |||
59 | /** | ||
60 | * How long do we wait at least before retransmitting ever? | ||
61 | */ | ||
62 | #define MIN_RTT_DELAY \ | ||
63 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75) | ||
64 | |||
65 | /** | ||
66 | * Maximum message ID into the future we accept for out-of-order messages. | ||
67 | * If the message is more than this into the future, we drop it. This is | ||
68 | * important both to detect values that are actually in the past, as well | ||
69 | * as to limit adversarially triggerable memory consumption. | ||
70 | * | ||
71 | * Note that right now we have "max_pending_messages = 4" hard-coded in | ||
72 | * the logic below, so a value of 4 would suffice here. But we plan to | ||
73 | * allow larger windows in the future... | ||
74 | */ | ||
75 | #define MAX_OUT_OF_ORDER_DISTANCE 1024 | ||
76 | |||
77 | |||
78 | /** | ||
79 | * All the states a channel can be in. | ||
80 | */ | ||
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 | void | ||
392 | GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct | ||
393 | GNUNET_CADET_RequestDropCadetMessage *message) | ||
394 | { | ||
395 | |||
396 | ch->type = message->type; | ||
397 | |||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Check if type of message is the one to drop. | ||
403 | * @param ch CadetChannel to check for message type to drop. | ||
404 | * @param message GNUNET_MessageHeader to compare the type with. | ||
405 | */ | ||
406 | int | ||
407 | GCCH_is_type_to_drop (struct CadetChannel *ch, const struct | ||
408 | GNUNET_MessageHeader *message) | ||
409 | { | ||
410 | |||
411 | if (ch->type == message->type) | ||
412 | { | ||
413 | ch->type = 0; | ||
414 | return GNUNET_YES; | ||
415 | } | ||
416 | else | ||
417 | return GNUNET_NO; | ||
418 | } | ||
419 | |||
420 | |||
421 | /** | ||
422 | * Get the static string for identification of the channel. | ||
423 | * | ||
424 | * @param ch Channel. | ||
425 | * | ||
426 | * @return Static string with the channel IDs. | ||
427 | */ | ||
428 | const char * | ||
429 | GCCH_2s (const struct CadetChannel *ch) | ||
430 | { | ||
431 | static char buf[128]; | ||
432 | |||
433 | GNUNET_snprintf (buf, | ||
434 | sizeof(buf), | ||
435 | "Channel %s:%s ctn:%X(%X/%X)", | ||
436 | (GNUNET_YES == ch->is_loopback) | ||
437 | ? "loopback" | ||
438 | : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))), | ||
439 | GNUNET_h2s (&ch->port), | ||
440 | ch->ctn.cn, | ||
441 | (NULL == ch->owner) | ||
442 | ? 0 | ||
443 | : ntohl (ch->owner->ccn.channel_of_client), | ||
444 | (NULL == ch->dest) | ||
445 | ? 0 | ||
446 | : ntohl (ch->dest->ccn.channel_of_client)); | ||
447 | return buf; | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * Hash the @a port and @a initiator and @a listener to | ||
453 | * calculate the "challenge" @a h_port we send to the other | ||
454 | * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN. | ||
455 | * | ||
456 | * @param[out] h_port set to the hash of @a port, @a initiator and @a listener | ||
457 | * @param port cadet port, as seen by CADET clients | ||
458 | * @param listener peer that is listining on @a port | ||
459 | */ | ||
460 | void | ||
461 | GCCH_hash_port (struct GNUNET_HashCode *h_port, | ||
462 | const struct GNUNET_HashCode *port, | ||
463 | const struct GNUNET_PeerIdentity *listener) | ||
464 | { | ||
465 | struct GNUNET_HashContext *hc; | ||
466 | |||
467 | hc = GNUNET_CRYPTO_hash_context_start (); | ||
468 | GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port)); | ||
469 | GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener)); | ||
470 | GNUNET_CRYPTO_hash_context_finish (hc, h_port); | ||
471 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
472 | "Calculated port hash %s\n", | ||
473 | GNUNET_h2s (h_port)); | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * Get the channel's public ID. | ||
479 | * | ||
480 | * @param ch Channel. | ||
481 | * | ||
482 | * @return ID used to identify the channel with the remote peer. | ||
483 | */ | ||
484 | struct GNUNET_CADET_ChannelTunnelNumber | ||
485 | GCCH_get_id (const struct CadetChannel *ch) | ||
486 | { | ||
487 | return ch->ctn; | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Release memory associated with @a ccc | ||
493 | * | ||
494 | * @param ccc data structure to clean up | ||
495 | */ | ||
496 | static void | ||
497 | free_channel_client (struct CadetChannelClient *ccc) | ||
498 | { | ||
499 | struct CadetOutOfOrderMessage *com; | ||
500 | |||
501 | while (NULL != (com = ccc->head_recv)) | ||
502 | { | ||
503 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
504 | ccc->num_recv--; | ||
505 | GNUNET_MQ_discard (com->env); | ||
506 | GNUNET_free (com); | ||
507 | } | ||
508 | GNUNET_free (ccc); | ||
509 | } | ||
510 | |||
511 | |||
512 | /** | ||
513 | * Destroy the given channel. | ||
514 | * | ||
515 | * @param ch channel to destroy | ||
516 | */ | ||
517 | static void | ||
518 | channel_destroy (struct CadetChannel *ch) | ||
519 | { | ||
520 | struct CadetReliableMessage *crm; | ||
521 | |||
522 | while (NULL != (crm = ch->head_sent)) | ||
523 | { | ||
524 | GNUNET_assert (ch == crm->ch); | ||
525 | if (NULL != crm->qe) | ||
526 | { | ||
527 | GCT_send_cancel (crm->qe); | ||
528 | crm->qe = NULL; | ||
529 | } | ||
530 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
531 | GNUNET_free (crm->data_message); | ||
532 | GNUNET_free (crm); | ||
533 | } | ||
534 | if (CADET_CHANNEL_LOOSE == ch->state) | ||
535 | { | ||
536 | GSC_drop_loose_channel (&ch->h_port, ch); | ||
537 | } | ||
538 | if (NULL != ch->owner) | ||
539 | { | ||
540 | free_channel_client (ch->owner); | ||
541 | ch->owner = NULL; | ||
542 | } | ||
543 | if (NULL != ch->dest) | ||
544 | { | ||
545 | free_channel_client (ch->dest); | ||
546 | ch->dest = NULL; | ||
547 | } | ||
548 | if (NULL != ch->last_control_qe) | ||
549 | { | ||
550 | GCT_send_cancel (ch->last_control_qe); | ||
551 | ch->last_control_qe = NULL; | ||
552 | } | ||
553 | if (NULL != ch->retry_data_task) | ||
554 | { | ||
555 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
556 | ch->retry_data_task = NULL; | ||
557 | } | ||
558 | if (NULL != ch->retry_control_task) | ||
559 | { | ||
560 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
561 | ch->retry_control_task = NULL; | ||
562 | } | ||
563 | if (GNUNET_NO == ch->is_loopback) | ||
564 | { | ||
565 | GCT_remove_channel (ch->t, ch, ch->ctn); | ||
566 | ch->t = NULL; | ||
567 | } | ||
568 | GNUNET_free (ch); | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Send a channel create message. | ||
574 | * | ||
575 | * @param cls Channel for which to send. | ||
576 | */ | ||
577 | static void | ||
578 | send_channel_open (void *cls); | ||
579 | |||
580 | |||
581 | /** | ||
582 | * Function called once the tunnel confirms that we sent the | ||
583 | * create message. Delays for a bit until we retry. | ||
584 | * | ||
585 | * @param cls our `struct CadetChannel`. | ||
586 | * @param cid identifier of the connection within the tunnel, NULL | ||
587 | * if transmission failed | ||
588 | */ | ||
589 | static void | ||
590 | channel_open_sent_cb (void *cls, | ||
591 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
592 | { | ||
593 | struct CadetChannel *ch = cls; | ||
594 | |||
595 | GNUNET_assert (NULL != ch->last_control_qe); | ||
596 | ch->last_control_qe = NULL; | ||
597 | ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time); | ||
598 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
599 | "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n", | ||
600 | GCCH_2s (ch), | ||
601 | GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES)); | ||
602 | ch->retry_control_task = | ||
603 | GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch); | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Send a channel open message. | ||
609 | * | ||
610 | * @param cls Channel for which to send. | ||
611 | */ | ||
612 | static void | ||
613 | send_channel_open (void *cls) | ||
614 | { | ||
615 | struct CadetChannel *ch = cls; | ||
616 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | ||
617 | |||
618 | ch->retry_control_task = NULL; | ||
619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | "Sending CHANNEL_OPEN message for %s\n", | ||
621 | GCCH_2s (ch)); | ||
622 | msgcc.header.size = htons (sizeof(msgcc)); | ||
623 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | ||
624 | // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed. | ||
625 | msgcc.opt = 2; | ||
626 | msgcc.h_port = ch->h_port; | ||
627 | msgcc.ctn = ch->ctn; | ||
628 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
629 | if (NULL != ch->last_control_qe) | ||
630 | GCT_send_cancel (ch->last_control_qe); | ||
631 | ch->last_control_qe = | ||
632 | GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn); | ||
633 | GNUNET_assert (NULL == ch->retry_control_task); | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Function called once and only once after a channel was bound | ||
639 | * to its tunnel via #GCT_add_channel() is ready for transmission. | ||
640 | * Note that this is only the case for channels that this peer | ||
641 | * initiates, as for incoming channels we assume that they are | ||
642 | * ready for transmission immediately upon receiving the open | ||
643 | * message. Used to bootstrap the #GCT_send() process. | ||
644 | * | ||
645 | * @param ch the channel for which the tunnel is now ready | ||
646 | */ | ||
647 | void | ||
648 | GCCH_tunnel_up (struct CadetChannel *ch) | ||
649 | { | ||
650 | GNUNET_assert (NULL == ch->retry_control_task); | ||
651 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
652 | "Tunnel up, sending CHANNEL_OPEN on %s now\n", | ||
653 | GCCH_2s (ch)); | ||
654 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch); | ||
655 | } | ||
656 | |||
657 | |||
658 | struct CadetChannel * | ||
659 | GCCH_channel_local_new (struct CadetClient *owner, | ||
660 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
661 | struct CadetPeer *destination, | ||
662 | const struct GNUNET_HashCode *port, | ||
663 | uint32_t options) | ||
664 | { | ||
665 | struct CadetChannel *ch; | ||
666 | struct CadetChannelClient *ccco; | ||
667 | |||
668 | ccco = GNUNET_new (struct CadetChannelClient); | ||
669 | ccco->c = owner; | ||
670 | ccco->ccn = ccn; | ||
671 | ccco->client_ready = GNUNET_YES; | ||
672 | |||
673 | ch = GNUNET_new (struct CadetChannel); | ||
674 | ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */ | ||
675 | ch->nobuffer = GNUNET_NO; | ||
676 | ch->reliable = GNUNET_YES; | ||
677 | ch->out_of_order = GNUNET_NO; | ||
678 | ch->max_pending_messages = | ||
679 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
680 | ch->owner = ccco; | ||
681 | ch->port = *port; | ||
682 | GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination)); | ||
683 | if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination))) | ||
684 | { | ||
685 | struct OpenPort *op; | ||
686 | |||
687 | ch->is_loopback = GNUNET_YES; | ||
688 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port); | ||
689 | if (NULL == op) | ||
690 | { | ||
691 | /* port closed, wait for it to possibly open */ | ||
692 | ch->state = CADET_CHANNEL_LOOSE; | ||
693 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
694 | loose_channels, | ||
695 | &ch->h_port, | ||
696 | ch, | ||
697 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
698 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
699 | "Created loose incoming loopback channel to port %s\n", | ||
700 | GNUNET_h2s (&ch->port)); | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | GCCH_bind (ch, op->c, &op->port); | ||
705 | } | ||
706 | } | ||
707 | else | ||
708 | { | ||
709 | ch->t = GCP_get_tunnel (destination, GNUNET_YES); | ||
710 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
711 | ch->ctn = GCT_add_channel (ch->t, ch); | ||
712 | } | ||
713 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
715 | "Created channel to port %s at peer %s for %s using %s\n", | ||
716 | GNUNET_h2s (port), | ||
717 | GCP_2s (destination), | ||
718 | GSC_2s (owner), | ||
719 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); | ||
720 | return ch; | ||
721 | } | ||
722 | |||
723 | |||
724 | /** | ||
725 | * We had an incoming channel to a port that is closed. | ||
726 | * It has not been opened for a while, drop it. | ||
727 | * | ||
728 | * @param cls the channel to drop | ||
729 | */ | ||
730 | static void | ||
731 | timeout_closed_cb (void *cls) | ||
732 | { | ||
733 | struct CadetChannel *ch = cls; | ||
734 | |||
735 | ch->retry_control_task = NULL; | ||
736 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
737 | "Closing incoming channel to port %s from peer %s due to timeout\n", | ||
738 | GNUNET_h2s (&ch->port), | ||
739 | GCP_2s (GCT_get_destination (ch->t))); | ||
740 | channel_destroy (ch); | ||
741 | } | ||
742 | |||
743 | |||
744 | struct CadetChannel * | ||
745 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
746 | struct GNUNET_CADET_ChannelTunnelNumber ctn, | ||
747 | const struct GNUNET_HashCode *h_port, | ||
748 | uint32_t options) | ||
749 | { | ||
750 | struct CadetChannel *ch; | ||
751 | struct OpenPort *op; | ||
752 | |||
753 | ch = GNUNET_new (struct CadetChannel); | ||
754 | ch->h_port = *h_port; | ||
755 | ch->t = t; | ||
756 | ch->ctn = ctn; | ||
757 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
758 | ch->nobuffer = GNUNET_NO; | ||
759 | ch->reliable = GNUNET_YES; | ||
760 | ch->out_of_order = GNUNET_NO; | ||
761 | ch->max_pending_messages = | ||
762 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
763 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
764 | |||
765 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port); | ||
766 | if (NULL == op) | ||
767 | { | ||
768 | /* port closed, wait for it to possibly open */ | ||
769 | ch->state = CADET_CHANNEL_LOOSE; | ||
770 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
771 | loose_channels, | ||
772 | &ch->h_port, | ||
773 | ch, | ||
774 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
775 | GNUNET_assert (NULL == ch->retry_control_task); | ||
776 | ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT, | ||
777 | &timeout_closed_cb, | ||
778 | ch); | ||
779 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
780 | "Created loose incoming channel to port %s from peer %s\n", | ||
781 | GNUNET_h2s (&ch->port), | ||
782 | GCP_2s (GCT_get_destination (ch->t))); | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | GCCH_bind (ch, op->c, &op->port); | ||
787 | } | ||
788 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
789 | return ch; | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Function called once the tunnel confirms that we sent the | ||
795 | * ACK message. Just remembers it was sent, we do not expect | ||
796 | * ACKs for ACKs ;-). | ||
797 | * | ||
798 | * @param cls our `struct CadetChannel`. | ||
799 | * @param cid identifier of the connection within the tunnel, NULL | ||
800 | * if transmission failed | ||
801 | */ | ||
802 | static void | ||
803 | send_ack_cb (void *cls, | ||
804 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
805 | { | ||
806 | struct CadetChannel *ch = cls; | ||
807 | |||
808 | GNUNET_assert (NULL != ch->last_control_qe); | ||
809 | ch->last_control_qe = NULL; | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer. | ||
815 | * | ||
816 | * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for | ||
817 | */ | ||
818 | static void | ||
819 | send_channel_data_ack (struct CadetChannel *ch) | ||
820 | { | ||
821 | struct GNUNET_CADET_ChannelDataAckMessage msg; | ||
822 | |||
823 | if (GNUNET_NO == ch->reliable) | ||
824 | return; /* no ACKs */ | ||
825 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | ||
826 | msg.header.size = htons (sizeof(msg)); | ||
827 | msg.ctn = ch->ctn; | ||
828 | msg.mid.mid = htonl (ntohl (ch->mid_recv.mid)); | ||
829 | msg.futures = GNUNET_htonll (ch->mid_futures); | ||
830 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
831 | "Sending DATA_ACK %u:%llX via %s\n", | ||
832 | (unsigned int) ntohl (msg.mid.mid), | ||
833 | (unsigned long long) ch->mid_futures, | ||
834 | GCCH_2s (ch)); | ||
835 | if (NULL != ch->last_control_qe) | ||
836 | GCT_send_cancel (ch->last_control_qe); | ||
837 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
838 | &msg.ctn); | ||
839 | } | ||
840 | |||
841 | |||
842 | /** | ||
843 | * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the | ||
844 | * connection is up. | ||
845 | * | ||
846 | * @param cls the `struct CadetChannel` | ||
847 | */ | ||
848 | static void | ||
849 | send_open_ack (void *cls) | ||
850 | { | ||
851 | struct CadetChannel *ch = cls; | ||
852 | struct GNUNET_CADET_ChannelOpenAckMessage msg; | ||
853 | |||
854 | ch->retry_control_task = NULL; | ||
855 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
856 | "Sending CHANNEL_OPEN_ACK on %s\n", | ||
857 | GCCH_2s (ch)); | ||
858 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | ||
859 | msg.header.size = htons (sizeof(msg)); | ||
860 | msg.reserved = htonl (0); | ||
861 | msg.ctn = ch->ctn; | ||
862 | msg.port = ch->port; | ||
863 | if (NULL != ch->last_control_qe) | ||
864 | GCT_send_cancel (ch->last_control_qe); | ||
865 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
866 | &msg.ctn); | ||
867 | } | ||
868 | |||
869 | |||
870 | /** | ||
871 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
872 | * this channel. If the binding was successful, (re)transmit the | ||
873 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
874 | * | ||
875 | * @param ch channel that got the duplicate open | ||
876 | * @param cti identifier of the connection that delivered the message | ||
877 | */ | ||
878 | void | ||
879 | GCCH_handle_duplicate_open ( | ||
880 | struct CadetChannel *ch, | ||
881 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
882 | { | ||
883 | if (NULL == ch->dest) | ||
884 | { | ||
885 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
886 | "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n", | ||
887 | GCCH_2s (ch)); | ||
888 | return; | ||
889 | } | ||
890 | if (NULL != ch->retry_control_task) | ||
891 | { | ||
892 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
893 | "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n", | ||
894 | GCCH_2s (ch)); | ||
895 | return; | ||
896 | } | ||
897 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
898 | "Retransmitting CHANNEL_OPEN_ACK on %s\n", | ||
899 | GCCH_2s (ch)); | ||
900 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages. | ||
906 | * | ||
907 | * @param ch channel the ack is for | ||
908 | * @param to_owner #GNUNET_YES to send to owner, | ||
909 | * #GNUNET_NO to send to dest | ||
910 | */ | ||
911 | static void | ||
912 | send_ack_to_client (struct CadetChannel *ch, int to_owner) | ||
913 | { | ||
914 | struct GNUNET_MQ_Envelope *env; | ||
915 | struct GNUNET_CADET_LocalAck *ack; | ||
916 | struct CadetChannelClient *ccc; | ||
917 | |||
918 | ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest; | ||
919 | if (NULL == ccc) | ||
920 | { | ||
921 | /* This can happen if we are just getting ACKs after | ||
922 | our local client already disconnected. */ | ||
923 | GNUNET_assert (GNUNET_YES == ch->destroy); | ||
924 | return; | ||
925 | } | ||
926 | env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
927 | ack->ccn = ccc->ccn; | ||
928 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
929 | "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n", | ||
930 | GSC_2s (ccc->c), | ||
931 | (GNUNET_YES == to_owner) ? "owner" : "dest", | ||
932 | ntohl (ack->ccn.channel_of_client), | ||
933 | ch->pending_messages, | ||
934 | ch->max_pending_messages); | ||
935 | GSC_send_to_client (ccc->c, env); | ||
936 | } | ||
937 | |||
938 | |||
939 | void | ||
940 | GCCH_bind (struct CadetChannel *ch, | ||
941 | struct CadetClient *c, | ||
942 | const struct GNUNET_HashCode *port) | ||
943 | { | ||
944 | uint32_t options; | ||
945 | struct CadetChannelClient *cccd; | ||
946 | |||
947 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
948 | "Binding %s from %s to port %s of %s\n", | ||
949 | GCCH_2s (ch), | ||
950 | GCT_2s (ch->t), | ||
951 | GNUNET_h2s (&ch->port), | ||
952 | GSC_2s (c)); | ||
953 | if (NULL != ch->retry_control_task) | ||
954 | { | ||
955 | /* there might be a timeout task here */ | ||
956 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
957 | ch->retry_control_task = NULL; | ||
958 | } | ||
959 | options = 0; | ||
960 | cccd = GNUNET_new (struct CadetChannelClient); | ||
961 | GNUNET_assert (NULL == ch->dest); | ||
962 | ch->dest = cccd; | ||
963 | ch->port = *port; | ||
964 | cccd->c = c; | ||
965 | cccd->client_ready = GNUNET_YES; | ||
966 | cccd->ccn = GSC_bind (c, | ||
967 | ch, | ||
968 | (GNUNET_YES == ch->is_loopback) | ||
969 | ? GCP_get (&my_full_id, GNUNET_YES) | ||
970 | : GCT_get_destination (ch->t), | ||
971 | port, | ||
972 | options); | ||
973 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
974 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
975 | ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */ | ||
976 | if (GNUNET_YES == ch->is_loopback) | ||
977 | { | ||
978 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
979 | GCCH_handle_channel_open_ack (ch, NULL, port); | ||
980 | } | ||
981 | else | ||
982 | { | ||
983 | /* notify other peer that we accepted the connection */ | ||
984 | ch->state = CADET_CHANNEL_READY; | ||
985 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
986 | } | ||
987 | /* give client it's initial supply of ACKs */ | ||
988 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
989 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
990 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
991 | send_ack_to_client (ch, GNUNET_NO); | ||
992 | } | ||
993 | |||
994 | |||
995 | /** | ||
996 | * One of our clients has disconnected, tell the other one that we | ||
997 | * are finished. Done asynchronously to avoid concurrent modification | ||
998 | * issues if this is the same client. | ||
999 | * | ||
1000 | * @param cls the `struct CadetChannel` where one of the ends is now dead | ||
1001 | */ | ||
1002 | static void | ||
1003 | signal_remote_destroy_cb (void *cls) | ||
1004 | { | ||
1005 | struct CadetChannel *ch = cls; | ||
1006 | struct CadetChannelClient *ccc; | ||
1007 | |||
1008 | /* Find which end is left... */ | ||
1009 | ch->retry_control_task = NULL; | ||
1010 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1011 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1012 | channel_destroy (ch); | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /** | ||
1017 | * Destroy locally created channel. Called by the local client, so no | ||
1018 | * need to tell the client. | ||
1019 | * | ||
1020 | * @param ch channel to destroy | ||
1021 | * @param c client that caused the destruction | ||
1022 | * @param ccn client number of the client @a c | ||
1023 | */ | ||
1024 | void | ||
1025 | GCCH_channel_local_destroy (struct CadetChannel *ch, | ||
1026 | struct CadetClient *c, | ||
1027 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1028 | { | ||
1029 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1030 | "%s asks for destruction of %s\n", | ||
1031 | GSC_2s (c), | ||
1032 | GCCH_2s (ch)); | ||
1033 | GNUNET_assert (NULL != c); | ||
1034 | if ((NULL != ch->owner) && (c == ch->owner->c) && | ||
1035 | (ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1036 | { | ||
1037 | free_channel_client (ch->owner); | ||
1038 | ch->owner = NULL; | ||
1039 | } | ||
1040 | else if ((NULL != ch->dest) && (c == ch->dest->c) && | ||
1041 | (ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1042 | { | ||
1043 | free_channel_client (ch->dest); | ||
1044 | ch->dest = NULL; | ||
1045 | } | ||
1046 | else | ||
1047 | { | ||
1048 | GNUNET_assert (0); | ||
1049 | } | ||
1050 | |||
1051 | if (GNUNET_YES == ch->destroy) | ||
1052 | { | ||
1053 | /* other end already destroyed, with the local client gone, no need | ||
1054 | to finish transmissions, just destroy immediately. */ | ||
1055 | channel_destroy (ch); | ||
1056 | return; | ||
1057 | } | ||
1058 | if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1059 | { | ||
1060 | /* Wait for other end to destroy us as well, | ||
1061 | and otherwise allow send queue to be transmitted first */ | ||
1062 | ch->destroy = GNUNET_YES; | ||
1063 | return; | ||
1064 | } | ||
1065 | if ((GNUNET_YES == ch->is_loopback) && | ||
1066 | ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1067 | { | ||
1068 | if (NULL != ch->retry_control_task) | ||
1069 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1070 | ch->retry_control_task = | ||
1071 | GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch); | ||
1072 | return; | ||
1073 | } | ||
1074 | if (GNUNET_NO == ch->is_loopback) | ||
1075 | { | ||
1076 | /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */ | ||
1077 | switch (ch->state) | ||
1078 | { | ||
1079 | case CADET_CHANNEL_NEW: | ||
1080 | /* We gave up on a channel that we created as a client to a remote | ||
1081 | target, but that never went anywhere. Nothing to do here. */ | ||
1082 | break; | ||
1083 | |||
1084 | case CADET_CHANNEL_LOOSE: | ||
1085 | break; | ||
1086 | |||
1087 | default: | ||
1088 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1089 | } | ||
1090 | } | ||
1091 | /* Nothing left to do, just finish destruction */ | ||
1092 | channel_destroy (ch); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | void | ||
1097 | GCCH_handle_channel_open_ack ( | ||
1098 | struct CadetChannel *ch, | ||
1099 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1100 | const struct GNUNET_HashCode *port) | ||
1101 | { | ||
1102 | switch (ch->state) | ||
1103 | { | ||
1104 | case CADET_CHANNEL_NEW: | ||
1105 | /* this should be impossible */ | ||
1106 | GNUNET_break (0); | ||
1107 | break; | ||
1108 | |||
1109 | case CADET_CHANNEL_LOOSE: | ||
1110 | /* This makes no sense. */ | ||
1111 | GNUNET_break_op (0); | ||
1112 | break; | ||
1113 | |||
1114 | case CADET_CHANNEL_OPEN_SENT: | ||
1115 | if (NULL == ch->owner) | ||
1116 | { | ||
1117 | /* We're not the owner, wrong direction! */ | ||
1118 | GNUNET_break_op (0); | ||
1119 | return; | ||
1120 | } | ||
1121 | if (0 != GNUNET_memcmp (&ch->port, port)) | ||
1122 | { | ||
1123 | /* Other peer failed to provide the right port, | ||
1124 | refuse connection. */ | ||
1125 | GNUNET_break_op (0); | ||
1126 | return; | ||
1127 | } | ||
1128 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1129 | "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n", | ||
1130 | GCCH_2s (ch)); | ||
1131 | if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */ | ||
1132 | { | ||
1133 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1134 | ch->retry_control_task = NULL; | ||
1135 | } | ||
1136 | ch->state = CADET_CHANNEL_READY; | ||
1137 | /* On first connect, send client as many ACKs as we allow messages | ||
1138 | to be buffered! */ | ||
1139 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
1140 | send_ack_to_client (ch, GNUNET_YES); | ||
1141 | break; | ||
1142 | |||
1143 | case CADET_CHANNEL_READY: | ||
1144 | /* duplicate ACK, maybe we retried the CREATE. Ignore. */ | ||
1145 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1146 | "Received duplicate channel OPEN_ACK for %s\n", | ||
1147 | GCCH_2s (ch)); | ||
1148 | GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO); | ||
1149 | break; | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | /** | ||
1155 | * Test if element @a e1 comes before element @a e2. | ||
1156 | * | ||
1157 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1158 | * @param m1 a message of to sort | ||
1159 | * @param m2 another message to sort | ||
1160 | * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO | ||
1161 | */ | ||
1162 | static int | ||
1163 | is_before (void *cls, | ||
1164 | struct CadetOutOfOrderMessage *m1, | ||
1165 | struct CadetOutOfOrderMessage *m2) | ||
1166 | { | ||
1167 | int *duplicate = cls; | ||
1168 | uint32_t v1 = ntohl (m1->mid.mid); | ||
1169 | uint32_t v2 = ntohl (m2->mid.mid); | ||
1170 | uint32_t delta; | ||
1171 | |||
1172 | delta = v2 - v1; | ||
1173 | if (0 == delta) | ||
1174 | *duplicate = GNUNET_YES; | ||
1175 | if (delta > (uint32_t) INT_MAX) | ||
1176 | { | ||
1177 | /* in overflow range, we can safely assume we wrapped around */ | ||
1178 | return GNUNET_NO; | ||
1179 | } | ||
1180 | else | ||
1181 | { | ||
1182 | /* result is small, thus v2 > v1, thus m1 < m2 */ | ||
1183 | return GNUNET_YES; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1187 | |||
1188 | void | ||
1189 | GCCH_handle_channel_plaintext_data ( | ||
1190 | struct CadetChannel *ch, | ||
1191 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1192 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
1193 | { | ||
1194 | struct GNUNET_MQ_Envelope *env; | ||
1195 | struct GNUNET_CADET_LocalData *ld; | ||
1196 | struct CadetChannelClient *ccc; | ||
1197 | size_t payload_size; | ||
1198 | struct CadetOutOfOrderMessage *com; | ||
1199 | int duplicate; | ||
1200 | uint32_t mid_min; | ||
1201 | uint32_t mid_max; | ||
1202 | uint32_t mid_msg; | ||
1203 | uint32_t delta; | ||
1204 | |||
1205 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1206 | if ((NULL == ch->owner) && (NULL == ch->dest)) | ||
1207 | { | ||
1208 | /* This client is gone, but we still have messages to send to | ||
1209 | the other end (which is why @a ch is not yet dead). However, | ||
1210 | we cannot pass messages to our client anymore. */ | ||
1211 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1212 | "Dropping incoming payload on %s as this end is already closed\n", | ||
1213 | GCCH_2s (ch)); | ||
1214 | /* send back DESTROY notification to stop further retransmissions! */ | ||
1215 | if (GNUNET_YES == ch->destroy) | ||
1216 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1217 | return; | ||
1218 | } | ||
1219 | payload_size = ntohs (msg->header.size) - sizeof(*msg); | ||
1220 | env = GNUNET_MQ_msg_extra (ld, | ||
1221 | payload_size, | ||
1222 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1223 | ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn; | ||
1224 | GNUNET_memcpy (&ld[1], &msg[1], payload_size); | ||
1225 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1226 | if (GNUNET_YES == ccc->client_ready) | ||
1227 | { | ||
1228 | /* | ||
1229 | * We ad-hoc send the message if | ||
1230 | * - The channel is out-of-order | ||
1231 | * - The channel is reliable and MID matches next expected MID | ||
1232 | * - The channel is unreliable and MID is before lowest seen MID | ||
1233 | */if ((GNUNET_YES == ch->out_of_order) || | ||
1234 | ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) || | ||
1235 | ((GNUNET_NO == ch->reliable) && | ||
1236 | (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) && | ||
1237 | ((NULL == ccc->head_recv) || | ||
1238 | (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid))))) | ||
1239 | { | ||
1240 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1241 | "Giving %u bytes of payload with MID %u from %s to client %s\n", | ||
1242 | (unsigned int) payload_size, | ||
1243 | ntohl (msg->mid.mid), | ||
1244 | GCCH_2s (ch), | ||
1245 | GSC_2s (ccc->c)); | ||
1246 | ccc->client_ready = GNUNET_NO; | ||
1247 | GSC_send_to_client (ccc->c, env); | ||
1248 | if (GNUNET_NO == ch->out_of_order) | ||
1249 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1250 | else | ||
1251 | ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); | ||
1252 | ch->mid_futures >>= 1; | ||
1253 | if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable)) | ||
1254 | { | ||
1255 | /* possibly shift by more if we skipped messages */ | ||
1256 | uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid); | ||
1257 | |||
1258 | if (delta > 63) | ||
1259 | ch->mid_futures = 0; | ||
1260 | else | ||
1261 | ch->mid_futures >>= delta; | ||
1262 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1263 | } | ||
1264 | send_channel_data_ack (ch); | ||
1265 | return; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | if (GNUNET_YES == ch->reliable) | ||
1270 | { | ||
1271 | /* check if message ought to be dropped because it is ancient/too distant/duplicate */ | ||
1272 | mid_min = ntohl (ch->mid_recv.mid); | ||
1273 | mid_max = mid_min + ch->max_pending_messages; | ||
1274 | mid_msg = ntohl (msg->mid.mid); | ||
1275 | if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) || | ||
1276 | ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages)) | ||
1277 | { | ||
1278 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1279 | "%s at %u drops ancient or far-future message %u\n", | ||
1280 | GCCH_2s (ch), | ||
1281 | (unsigned int) mid_min, | ||
1282 | ntohl (msg->mid.mid)); | ||
1283 | |||
1284 | GNUNET_STATISTICS_update (stats, | ||
1285 | "# duplicate DATA (ancient or future)", | ||
1286 | 1, | ||
1287 | GNUNET_NO); | ||
1288 | GNUNET_MQ_discard (env); | ||
1289 | send_channel_data_ack (ch); | ||
1290 | return; | ||
1291 | } | ||
1292 | /* mark bit for future ACKs */ | ||
1293 | delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */ | ||
1294 | if (delta < 64) | ||
1295 | { | ||
1296 | if (0 != (ch->mid_futures & (1LLU << delta))) | ||
1297 | { | ||
1298 | /* Duplicate within the queue, drop also */ | ||
1299 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1300 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1301 | (unsigned int) payload_size, | ||
1302 | GCCH_2s (ch), | ||
1303 | ntohl (msg->mid.mid)); | ||
1304 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1305 | GNUNET_MQ_discard (env); | ||
1306 | send_channel_data_ack (ch); | ||
1307 | return; | ||
1308 | } | ||
1309 | ch->mid_futures |= (1LLU << delta); | ||
1310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1311 | "Marked bit %llX for mid %u (base: %u); now: %llX\n", | ||
1312 | (1LLU << delta), | ||
1313 | mid_msg, | ||
1314 | mid_min, | ||
1315 | (unsigned long long) ch->mid_futures); | ||
1316 | } | ||
1317 | } | ||
1318 | else /* ! ch->reliable */ | ||
1319 | { | ||
1320 | struct CadetOutOfOrderMessage *next_msg; | ||
1321 | |||
1322 | /** | ||
1323 | * We always send if possible in this case. | ||
1324 | * It is guaranteed that the queued MID < received MID | ||
1325 | **/ | ||
1326 | if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready)) | ||
1327 | { | ||
1328 | next_msg = ccc->head_recv; | ||
1329 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1330 | "Giving queued MID %u from %s to client %s\n", | ||
1331 | ntohl (next_msg->mid.mid), | ||
1332 | GCCH_2s (ch), | ||
1333 | GSC_2s (ccc->c)); | ||
1334 | ccc->client_ready = GNUNET_NO; | ||
1335 | GSC_send_to_client (ccc->c, next_msg->env); | ||
1336 | ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid)); | ||
1337 | ch->mid_futures >>= 1; | ||
1338 | send_channel_data_ack (ch); | ||
1339 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg); | ||
1340 | ccc->num_recv--; | ||
1341 | /* Do not process duplicate MID */ | ||
1342 | if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */ | ||
1343 | { | ||
1344 | /* Duplicate within the queue, drop */ | ||
1345 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1346 | "Message on %s (mid %u) dropped, duplicate\n", | ||
1347 | GCCH_2s (ch), | ||
1348 | ntohl (msg->mid.mid)); | ||
1349 | GNUNET_free (next_msg); | ||
1350 | GNUNET_MQ_discard (env); | ||
1351 | return; | ||
1352 | } | ||
1353 | GNUNET_free (next_msg); | ||
1354 | } | ||
1355 | |||
1356 | if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */ | ||
1357 | { | ||
1358 | /* Duplicate within the queue, drop */ | ||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1360 | "Message on %s (mid %u) dropped, old.\n", | ||
1361 | GCCH_2s (ch), | ||
1362 | ntohl (msg->mid.mid)); | ||
1363 | GNUNET_MQ_discard (env); | ||
1364 | return; | ||
1365 | } | ||
1366 | |||
1367 | /* Channel is unreliable, so we do not ACK. But we also cannot | ||
1368 | allow buffering everything, so check if we have space... */ | ||
1369 | if (ccc->num_recv >= ch->max_pending_messages) | ||
1370 | { | ||
1371 | struct CadetOutOfOrderMessage *drop; | ||
1372 | |||
1373 | /* Yep, need to drop. Drop the oldest message in | ||
1374 | the buffer. */ | ||
1375 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1376 | "Queue full due slow client on %s, dropping oldest message\n", | ||
1377 | GCCH_2s (ch)); | ||
1378 | GNUNET_STATISTICS_update (stats, | ||
1379 | "# messages dropped due to slow client", | ||
1380 | 1, | ||
1381 | GNUNET_NO); | ||
1382 | drop = ccc->head_recv; | ||
1383 | GNUNET_assert (NULL != drop); | ||
1384 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop); | ||
1385 | ccc->num_recv--; | ||
1386 | GNUNET_MQ_discard (drop->env); | ||
1387 | GNUNET_free (drop); | ||
1388 | } | ||
1389 | } | ||
1390 | |||
1391 | /* Insert message into sorted out-of-order queue */ | ||
1392 | com = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1393 | com->mid = msg->mid; | ||
1394 | com->env = env; | ||
1395 | duplicate = GNUNET_NO; | ||
1396 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage, | ||
1397 | is_before, | ||
1398 | &duplicate, | ||
1399 | ccc->head_recv, | ||
1400 | ccc->tail_recv, | ||
1401 | com); | ||
1402 | ccc->num_recv++; | ||
1403 | if (GNUNET_YES == duplicate) | ||
1404 | { | ||
1405 | /* Duplicate within the queue, drop also (this is not covered by | ||
1406 | the case above if "delta" >= 64, which could be the case if | ||
1407 | max_pending_messages is also >= 64 or if our client is unready | ||
1408 | and we are seeing retransmissions of the message our client is | ||
1409 | blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1410 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1411 | (unsigned int) payload_size, | ||
1412 | GCCH_2s (ch), | ||
1413 | ntohl (msg->mid.mid)); | ||
1414 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1415 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1416 | ccc->num_recv--; | ||
1417 | GNUNET_MQ_discard (com->env); | ||
1418 | GNUNET_free (com); | ||
1419 | send_channel_data_ack (ch); | ||
1420 | return; | ||
1421 | } | ||
1422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1423 | "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n", | ||
1424 | (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready", | ||
1425 | (unsigned int) payload_size, | ||
1426 | GCCH_2s (ch), | ||
1427 | ntohl (ccc->ccn.channel_of_client), | ||
1428 | ccc, | ||
1429 | ntohl (msg->mid.mid), | ||
1430 | ntohl (ch->mid_recv.mid)); | ||
1431 | /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and | ||
1432 | the sender may already be transmitting the previous one. Needs | ||
1433 | experimental evaluation to see if/when this ACK helps or | ||
1434 | hurts. (We might even want another option.) */ | ||
1435 | send_channel_data_ack (ch); | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * Function called once the tunnel has sent one of our messages. | ||
1441 | * If the message is unreliable, simply frees the `crm`. If the | ||
1442 | * message was reliable, calculate retransmission time and | ||
1443 | * wait for ACK (or retransmit). | ||
1444 | * | ||
1445 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1446 | * @param cid identifier of the connection within the tunnel, NULL | ||
1447 | * if transmission failed | ||
1448 | */ | ||
1449 | static void | ||
1450 | data_sent_cb (void *cls, | ||
1451 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * We need to retry a transmission, the last one took too long to | ||
1456 | * be acknowledged. | ||
1457 | * | ||
1458 | * @param cls the `struct CadetChannel` where we need to retransmit | ||
1459 | */ | ||
1460 | static void | ||
1461 | retry_transmission (void *cls) | ||
1462 | { | ||
1463 | struct CadetChannel *ch = cls; | ||
1464 | struct CadetReliableMessage *crm = ch->head_sent; | ||
1465 | |||
1466 | ch->retry_data_task = NULL; | ||
1467 | GNUNET_assert (NULL == crm->qe); | ||
1468 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1469 | "Retrying transmission on %s of message %u\n", | ||
1470 | GCCH_2s (ch), | ||
1471 | (unsigned int) ntohl (crm->data_message->mid.mid)); | ||
1472 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1473 | &crm->data_message->ctn); | ||
1474 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from | ||
1480 | * the queue and tell our client that it can send more. | ||
1481 | * | ||
1482 | * @param ch the channel that got the PLAINTEXT_DATA_ACK | ||
1483 | * @param cti identifier of the connection that delivered the message | ||
1484 | * @param crm the message that got acknowledged | ||
1485 | */ | ||
1486 | static void | ||
1487 | handle_matching_ack (struct CadetChannel *ch, | ||
1488 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1489 | struct CadetReliableMessage *crm) | ||
1490 | { | ||
1491 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1492 | ch->pending_messages--; | ||
1493 | GNUNET_assert (ch->pending_messages < ch->max_pending_messages); | ||
1494 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1495 | "Received DATA_ACK on %s for message %u (%u ACKs pending)\n", | ||
1496 | GCCH_2s (ch), | ||
1497 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1498 | ch->pending_messages); | ||
1499 | if (NULL != crm->qe) | ||
1500 | { | ||
1501 | GCT_send_cancel (crm->qe); | ||
1502 | crm->qe = NULL; | ||
1503 | } | ||
1504 | if ((1 == crm->num_transmissions) && (NULL != cti)) | ||
1505 | { | ||
1506 | GCC_ack_observed (cti); | ||
1507 | if (0 == GNUNET_memcmp (cti, &crm->connection_taken)) | ||
1508 | { | ||
1509 | GCC_latency_observed (cti, | ||
1510 | GNUNET_TIME_absolute_get_duration ( | ||
1511 | crm->first_transmission_time)); | ||
1512 | } | ||
1513 | } | ||
1514 | GNUNET_free (crm->data_message); | ||
1515 | GNUNET_free (crm); | ||
1516 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1517 | } | ||
1518 | |||
1519 | |||
1520 | /** | ||
1521 | * We got an acknowledgement for payload data for a channel. | ||
1522 | * Possibly resume transmissions. | ||
1523 | * | ||
1524 | * @param ch channel that got the ack | ||
1525 | * @param cti identifier of the connection that delivered the message | ||
1526 | * @param ack details about what was received | ||
1527 | */ | ||
1528 | void | ||
1529 | GCCH_handle_channel_plaintext_data_ack ( | ||
1530 | struct CadetChannel *ch, | ||
1531 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1532 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
1533 | { | ||
1534 | struct CadetReliableMessage *crm; | ||
1535 | struct CadetReliableMessage *crmn; | ||
1536 | int found; | ||
1537 | uint32_t mid_base; | ||
1538 | uint64_t mid_mask; | ||
1539 | unsigned int delta; | ||
1540 | |||
1541 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1542 | if (GNUNET_NO == ch->reliable) | ||
1543 | { | ||
1544 | /* not expecting ACKs on unreliable channel, odd */ | ||
1545 | GNUNET_break_op (0); | ||
1546 | return; | ||
1547 | } | ||
1548 | /* mid_base is the MID of the next message that the | ||
1549 | other peer expects (i.e. that is missing!), everything | ||
1550 | LOWER (but excluding mid_base itself) was received. */ | ||
1551 | mid_base = ntohl (ack->mid.mid); | ||
1552 | mid_mask = GNUNET_htonll (ack->futures); | ||
1553 | found = GNUNET_NO; | ||
1554 | for (crm = ch->head_sent; NULL != crm; crm = crmn) | ||
1555 | { | ||
1556 | crmn = crm->next; | ||
1557 | delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base); | ||
1558 | if (delta >= UINT_MAX - ch->max_pending_messages) | ||
1559 | { | ||
1560 | /* overflow, means crm was a bit in the past, so this ACK counts for it. */ | ||
1561 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1562 | "Got DATA_ACK with base %u satisfying past message %u on %s\n", | ||
1563 | (unsigned int) mid_base, | ||
1564 | ntohl (crm->data_message->mid.mid), | ||
1565 | GCCH_2s (ch)); | ||
1566 | handle_matching_ack (ch, cti, crm); | ||
1567 | found = GNUNET_YES; | ||
1568 | continue; | ||
1569 | } | ||
1570 | delta--; | ||
1571 | if (delta >= 64) | ||
1572 | continue; | ||
1573 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1574 | "Testing bit %llX for mid %u (base: %u)\n", | ||
1575 | (1LLU << delta), | ||
1576 | ntohl (crm->data_message->mid.mid), | ||
1577 | mid_base); | ||
1578 | if (0 != (mid_mask & (1LLU << delta))) | ||
1579 | { | ||
1580 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1581 | "Got DATA_ACK with mask for %u on %s\n", | ||
1582 | ntohl (crm->data_message->mid.mid), | ||
1583 | GCCH_2s (ch)); | ||
1584 | handle_matching_ack (ch, cti, crm); | ||
1585 | found = GNUNET_YES; | ||
1586 | } | ||
1587 | } | ||
1588 | if (GNUNET_NO == found) | ||
1589 | { | ||
1590 | /* ACK for message we already dropped, might have been a | ||
1591 | duplicate ACK? Ignore. */ | ||
1592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1593 | "Duplicate DATA_ACK on %s, ignoring\n", | ||
1594 | GCCH_2s (ch)); | ||
1595 | GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO); | ||
1596 | return; | ||
1597 | } | ||
1598 | if (NULL != ch->retry_data_task) | ||
1599 | { | ||
1600 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1601 | ch->retry_data_task = NULL; | ||
1602 | } | ||
1603 | if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe)) | ||
1604 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1605 | &retry_transmission, | ||
1606 | ch); | ||
1607 | } | ||
1608 | |||
1609 | |||
1610 | void | ||
1611 | GCCH_handle_remote_destroy ( | ||
1612 | struct CadetChannel *ch, | ||
1613 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
1614 | { | ||
1615 | struct CadetChannelClient *ccc; | ||
1616 | |||
1617 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1618 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1619 | "Received remote channel DESTROY for %s\n", | ||
1620 | GCCH_2s (ch)); | ||
1621 | if (GNUNET_YES == ch->destroy) | ||
1622 | { | ||
1623 | /* Local client already gone, this is instant-death. */ | ||
1624 | channel_destroy (ch); | ||
1625 | return; | ||
1626 | } | ||
1627 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1628 | if ((NULL != ccc) && (NULL != ccc->head_recv)) | ||
1629 | { | ||
1630 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1631 | "Lost end of transmission due to remote shutdown on %s\n", | ||
1632 | GCCH_2s (ch)); | ||
1633 | /* FIXME: change API to notify client about truncated transmission! */ | ||
1634 | } | ||
1635 | ch->destroy = GNUNET_YES; | ||
1636 | if (NULL != ccc) | ||
1637 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1638 | channel_destroy (ch); | ||
1639 | } | ||
1640 | |||
1641 | |||
1642 | /** | ||
1643 | * Test if element @a e1 comes before element @a e2. | ||
1644 | * | ||
1645 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1646 | * @param crm1 an element of to sort | ||
1647 | * @param crm2 another element to sort | ||
1648 | * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO | ||
1649 | */ | ||
1650 | static int | ||
1651 | cmp_crm_by_next_retry (void *cls, | ||
1652 | struct CadetReliableMessage *crm1, | ||
1653 | struct CadetReliableMessage *crm2) | ||
1654 | { | ||
1655 | if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us) | ||
1656 | return GNUNET_YES; | ||
1657 | return GNUNET_NO; | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /** | ||
1662 | * Function called once the tunnel has sent one of our messages. | ||
1663 | * If the message is unreliable, simply frees the `crm`. If the | ||
1664 | * message was reliable, calculate retransmission time and | ||
1665 | * wait for ACK (or retransmit). | ||
1666 | * | ||
1667 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1668 | * @param cid identifier of the connection within the tunnel, NULL | ||
1669 | * if transmission failed | ||
1670 | */ | ||
1671 | static void | ||
1672 | data_sent_cb (void *cls, | ||
1673 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
1674 | { | ||
1675 | struct CadetReliableMessage *crm = cls; | ||
1676 | struct CadetChannel *ch = crm->ch; | ||
1677 | |||
1678 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1679 | GNUNET_assert (NULL != crm->qe); | ||
1680 | crm->qe = NULL; | ||
1681 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1682 | if (GNUNET_NO == ch->reliable) | ||
1683 | { | ||
1684 | GNUNET_free (crm->data_message); | ||
1685 | GNUNET_free (crm); | ||
1686 | ch->pending_messages--; | ||
1687 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1688 | return; | ||
1689 | } | ||
1690 | if (NULL == cid) | ||
1691 | { | ||
1692 | /* There was an error sending. */ | ||
1693 | crm->num_transmissions = GNUNET_SYSERR; | ||
1694 | } | ||
1695 | else if (GNUNET_SYSERR != crm->num_transmissions) | ||
1696 | { | ||
1697 | /* Increment transmission counter, and possibly store @a cid | ||
1698 | if this was the first transmission. */ | ||
1699 | crm->num_transmissions++; | ||
1700 | if (1 == crm->num_transmissions) | ||
1701 | { | ||
1702 | crm->first_transmission_time = GNUNET_TIME_absolute_get (); | ||
1703 | crm->connection_taken = *cid; | ||
1704 | GCC_ack_expected (cid); | ||
1705 | } | ||
1706 | } | ||
1707 | if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid)) | ||
1708 | { | ||
1709 | struct CadetConnection *cc = GCC_lookup (cid); | ||
1710 | |||
1711 | if (NULL != cc) | ||
1712 | crm->retry_delay = GCC_get_metrics (cc)->aged_latency; | ||
1713 | else | ||
1714 | crm->retry_delay = ch->retry_time; | ||
1715 | } | ||
1716 | crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay); | ||
1717 | crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY); | ||
1718 | crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay); | ||
1719 | |||
1720 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage, | ||
1721 | cmp_crm_by_next_retry, | ||
1722 | NULL, | ||
1723 | ch->head_sent, | ||
1724 | ch->tail_sent, | ||
1725 | crm); | ||
1726 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1727 | "Message %u sent, next transmission on %s in %s\n", | ||
1728 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1729 | GCCH_2s (ch), | ||
1730 | GNUNET_STRINGS_relative_time_to_string ( | ||
1731 | GNUNET_TIME_absolute_get_remaining ( | ||
1732 | ch->head_sent->next_retry), | ||
1733 | GNUNET_YES)); | ||
1734 | if (NULL == ch->head_sent->qe) | ||
1735 | { | ||
1736 | if (NULL != ch->retry_data_task) | ||
1737 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1738 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1739 | &retry_transmission, | ||
1740 | ch); | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | |||
1745 | /** | ||
1746 | * Handle data given by a client. | ||
1747 | * | ||
1748 | * Check whether the client is allowed to send in this tunnel, save if | ||
1749 | * channel is reliable and send an ACK to the client if there is still | ||
1750 | * buffer space in the tunnel. | ||
1751 | * | ||
1752 | * @param ch Channel. | ||
1753 | * @param sender_ccn ccn of the sender | ||
1754 | * @param buf payload to transmit. | ||
1755 | * @param buf_len number of bytes in @a buf | ||
1756 | * @return #GNUNET_OK if everything goes well, | ||
1757 | * #GNUNET_SYSERR in case of an error. | ||
1758 | */ | ||
1759 | int | ||
1760 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
1761 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
1762 | const char *buf, | ||
1763 | size_t buf_len) | ||
1764 | { | ||
1765 | struct CadetReliableMessage *crm; | ||
1766 | |||
1767 | if (ch->pending_messages >= ch->max_pending_messages) | ||
1768 | { | ||
1769 | GNUNET_break (0); /* Fails: #5370 */ | ||
1770 | return GNUNET_SYSERR; | ||
1771 | } | ||
1772 | if (GNUNET_YES == ch->destroy) | ||
1773 | { | ||
1774 | /* we are going down, drop messages */ | ||
1775 | return GNUNET_OK; | ||
1776 | } | ||
1777 | ch->pending_messages++; | ||
1778 | |||
1779 | if (GNUNET_YES == ch->is_loopback) | ||
1780 | { | ||
1781 | struct CadetChannelClient *receiver; | ||
1782 | struct GNUNET_MQ_Envelope *env; | ||
1783 | struct GNUNET_CADET_LocalData *ld; | ||
1784 | int ack_to_owner; | ||
1785 | |||
1786 | env = | ||
1787 | GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1788 | if ((NULL != ch->owner) && | ||
1789 | (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1790 | { | ||
1791 | receiver = ch->dest; | ||
1792 | ack_to_owner = GNUNET_YES; | ||
1793 | } | ||
1794 | else if ((NULL != ch->dest) && | ||
1795 | (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1796 | { | ||
1797 | receiver = ch->owner; | ||
1798 | ack_to_owner = GNUNET_NO; | ||
1799 | } | ||
1800 | else | ||
1801 | { | ||
1802 | GNUNET_free (env); | ||
1803 | GNUNET_break (0); | ||
1804 | return GNUNET_SYSERR; | ||
1805 | } | ||
1806 | GNUNET_assert (NULL != receiver); | ||
1807 | ld->ccn = receiver->ccn; | ||
1808 | GNUNET_memcpy (&ld[1], buf, buf_len); | ||
1809 | if (GNUNET_YES == receiver->client_ready) | ||
1810 | { | ||
1811 | ch->pending_messages--; | ||
1812 | GSC_send_to_client (receiver->c, env); | ||
1813 | send_ack_to_client (ch, ack_to_owner); | ||
1814 | } | ||
1815 | else | ||
1816 | { | ||
1817 | struct CadetOutOfOrderMessage *oom; | ||
1818 | |||
1819 | oom = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1820 | oom->env = env; | ||
1821 | GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv, | ||
1822 | receiver->tail_recv, | ||
1823 | oom); | ||
1824 | receiver->num_recv++; | ||
1825 | } | ||
1826 | return GNUNET_OK; | ||
1827 | } | ||
1828 | |||
1829 | /* Everything is correct, send the message. */ | ||
1830 | crm = GNUNET_malloc (sizeof(*crm)); | ||
1831 | crm->ch = ch; | ||
1832 | crm->data_message = GNUNET_malloc ( | ||
1833 | sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1834 | crm->data_message->header.size = | ||
1835 | htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1836 | crm->data_message->header.type = | ||
1837 | htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1838 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1839 | crm->data_message->mid = ch->mid_send; | ||
1840 | crm->data_message->ctn = ch->ctn; | ||
1841 | GNUNET_memcpy (&crm->data_message[1], buf, buf_len); | ||
1842 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm); | ||
1843 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1844 | "Sending message %u from local client to %s with %lu bytes\n", | ||
1845 | ntohl (crm->data_message->mid.mid), | ||
1846 | GCCH_2s (ch), | ||
1847 | (unsigned long) buf_len); | ||
1848 | if (NULL != ch->retry_data_task) | ||
1849 | { | ||
1850 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1851 | ch->retry_data_task = NULL; | ||
1852 | } | ||
1853 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1854 | &crm->data_message->ctn); | ||
1855 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1856 | return GNUNET_OK; | ||
1857 | } | ||
1858 | |||
1859 | |||
1860 | void | ||
1861 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
1862 | struct GNUNET_CADET_ClientChannelNumber client_ccn) | ||
1863 | { | ||
1864 | struct CadetChannelClient *ccc; | ||
1865 | struct CadetOutOfOrderMessage *com; | ||
1866 | |||
1867 | if ((NULL != ch->owner) && | ||
1868 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1869 | ccc = ch->owner; | ||
1870 | else if ((NULL != ch->dest) && | ||
1871 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1872 | ccc = ch->dest; | ||
1873 | else | ||
1874 | GNUNET_assert (0); | ||
1875 | ccc->client_ready = GNUNET_YES; | ||
1876 | com = ccc->head_recv; | ||
1877 | if (NULL == com) | ||
1878 | { | ||
1879 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1880 | "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n", | ||
1881 | GSC_2s (ccc->c), | ||
1882 | ntohl (client_ccn.channel_of_client), | ||
1883 | GCCH_2s (ch), | ||
1884 | ntohl (ccc->ccn.channel_of_client), | ||
1885 | ccc); | ||
1886 | return; /* none pending */ | ||
1887 | } | ||
1888 | if (GNUNET_YES == ch->is_loopback) | ||
1889 | { | ||
1890 | int to_owner; | ||
1891 | |||
1892 | /* Messages are always in-order, just send */ | ||
1893 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1894 | ccc->num_recv--; | ||
1895 | GSC_send_to_client (ccc->c, com->env); | ||
1896 | /* Notify sender that we can receive more */ | ||
1897 | if ((NULL != ch->owner) && | ||
1898 | (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1899 | { | ||
1900 | to_owner = GNUNET_NO; | ||
1901 | } | ||
1902 | else | ||
1903 | { | ||
1904 | GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client == | ||
1905 | ch->dest->ccn.channel_of_client)); | ||
1906 | to_owner = GNUNET_YES; | ||
1907 | } | ||
1908 | send_ack_to_client (ch, to_owner); | ||
1909 | GNUNET_free (com); | ||
1910 | return; | ||
1911 | } | ||
1912 | |||
1913 | if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) && | ||
1914 | (GNUNET_YES == ch->reliable)) | ||
1915 | { | ||
1916 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1917 | "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n", | ||
1918 | GSC_2s (ccc->c), | ||
1919 | ntohl (ccc->ccn.channel_of_client), | ||
1920 | ntohl (com->mid.mid), | ||
1921 | ntohl (ch->mid_recv.mid)); | ||
1922 | return; /* missing next one in-order */ | ||
1923 | } | ||
1924 | |||
1925 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1926 | "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n", | ||
1927 | ntohl (com->mid.mid), | ||
1928 | GSC_2s (ccc->c), | ||
1929 | ntohl (ccc->ccn.channel_of_client), | ||
1930 | GCCH_2s (ch)); | ||
1931 | |||
1932 | /* all good, pass next message to client */ | ||
1933 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1934 | ccc->num_recv--; | ||
1935 | /* FIXME: if unreliable, this is not aggressive | ||
1936 | enough, as it would be OK to have lost some! */ | ||
1937 | |||
1938 | ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid)); | ||
1939 | ch->mid_futures >>= 1; /* equivalent to division by 2 */ | ||
1940 | ccc->client_ready = GNUNET_NO; | ||
1941 | GSC_send_to_client (ccc->c, com->env); | ||
1942 | GNUNET_free (com); | ||
1943 | send_channel_data_ack (ch); | ||
1944 | if (NULL != ccc->head_recv) | ||
1945 | return; | ||
1946 | if (GNUNET_NO == ch->destroy) | ||
1947 | return; | ||
1948 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1949 | channel_destroy (ch); | ||
1950 | } | ||
1951 | |||
1952 | |||
1953 | #define LOG2(level, ...) \ | ||
1954 | GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__) | ||
1955 | |||
1956 | |||
1957 | /** | ||
1958 | * Log channel info. | ||
1959 | * | ||
1960 | * @param ch Channel. | ||
1961 | * @param level Debug level to use. | ||
1962 | */ | ||
1963 | void | ||
1964 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) | ||
1965 | { | ||
1966 | #if ! defined(GNUNET_CULL_LOGGING) | ||
1967 | int do_log; | ||
1968 | |||
1969 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1970 | "cadet-chn", | ||
1971 | __FILE__, | ||
1972 | __FUNCTION__, | ||
1973 | __LINE__); | ||
1974 | if (0 == do_log) | ||
1975 | return; | ||
1976 | |||
1977 | if (NULL == ch) | ||
1978 | { | ||
1979 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | ||
1980 | return; | ||
1981 | } | ||
1982 | LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch); | ||
1983 | if (NULL != ch->owner) | ||
1984 | { | ||
1985 | LOG2 (level, | ||
1986 | "CHN origin %s ready %s local-id: %u\n", | ||
1987 | GSC_2s (ch->owner->c), | ||
1988 | ch->owner->client_ready ? "YES" : "NO", | ||
1989 | ntohl (ch->owner->ccn.channel_of_client)); | ||
1990 | } | ||
1991 | if (NULL != ch->dest) | ||
1992 | { | ||
1993 | LOG2 (level, | ||
1994 | "CHN destination %s ready %s local-id: %u\n", | ||
1995 | GSC_2s (ch->dest->c), | ||
1996 | ch->dest->client_ready ? "YES" : "NO", | ||
1997 | ntohl (ch->dest->ccn.channel_of_client)); | ||
1998 | } | ||
1999 | LOG2 (level, | ||
2000 | "CHN Message IDs recv: %d (%llX), send: %d\n", | ||
2001 | ntohl (ch->mid_recv.mid), | ||
2002 | (unsigned long long) ch->mid_futures, | ||
2003 | ntohl (ch->mid_send.mid)); | ||
2004 | #endif | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* end of gnunet-service-cadet_channel.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_channel.h b/src/service/cadet/gnunet-service-cadet_channel.h new file mode 100644 index 000000000..b09de883f --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_channel.h | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_channel.h | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H | ||
28 | #define GNUNET_SERVICE_CADET_CHANNEL_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "gnunet-service-cadet_peer.h" | ||
32 | #include "cadet_protocol.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * A channel is a bidirectional connection between two CADET | ||
37 | * clients. Communication can be reliable, unreliable, in-order | ||
38 | * or out-of-order. One client is the "local" client, this | ||
39 | * one initiated the connection. The other client is the | ||
40 | * "incoming" client, this one listened on a port to accept | ||
41 | * the connection from the "local" client. | ||
42 | */ | ||
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 | * Assign type of message to drop. | ||
71 | * @param ch CadetChannel to assign type to drop. | ||
72 | * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from. | ||
73 | */ | ||
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 h_port hash of desired local port | ||
178 | * @param options options for the channel | ||
179 | * @return handle to the new channel | ||
180 | */ | ||
181 | struct CadetChannel * | ||
182 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
183 | struct GNUNET_CADET_ChannelTunnelNumber chid, | ||
184 | const struct GNUNET_HashCode *h_port, | ||
185 | uint32_t options); | ||
186 | |||
187 | |||
188 | /** | ||
189 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
190 | * this channel. If the binding was successful, (re)transmit the | ||
191 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
192 | * | ||
193 | * @param ch channel that got the duplicate open | ||
194 | * @param cti identifier of the connection that delivered the message | ||
195 | */ | ||
196 | void | ||
197 | GCCH_handle_duplicate_open (struct CadetChannel *ch, | ||
198 | const struct | ||
199 | GNUNET_CADET_ConnectionTunnelIdentifier *cti); | ||
200 | |||
201 | |||
202 | /** | ||
203 | * We got payload data for a channel. Pass it on to the client | ||
204 | * and send an ACK to the other end (once flow control allows it!) | ||
205 | * | ||
206 | * @param ch channel that got data | ||
207 | * @param cti identifier of the connection that delivered the message | ||
208 | * @param msg message that was received | ||
209 | */ | ||
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). Verify that the | ||
238 | * other end really has the right port, and begin transmissions. | ||
239 | * | ||
240 | * @param ch channel to destroy | ||
241 | * @param cti identifier of the connection that delivered the message, | ||
242 | * NULL if the ACK was inferred because we got payload or are on loopback | ||
243 | * @param port port number (needed to verify receiver knows the port) | ||
244 | */ | ||
245 | void | ||
246 | GCCH_handle_channel_open_ack (struct CadetChannel *ch, | ||
247 | const struct | ||
248 | GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
249 | const struct GNUNET_HashCode *port); | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Destroy channel, based on the other peer closing the | ||
254 | * connection. Also needs to remove this channel from | ||
255 | * the tunnel. | ||
256 | * | ||
257 | * FIXME: need to make it possible to defer destruction until we have | ||
258 | * received all messages up to the destroy, and right now the destroy | ||
259 | * message (and this API) fails to give is the information we need! | ||
260 | * | ||
261 | * FIXME: also need to know if the other peer got a destroy from | ||
262 | * us before! | ||
263 | * | ||
264 | * @param ch channel to destroy | ||
265 | * @param cti identifier of the connection that delivered the message, | ||
266 | * NULL if we are simulating receiving a destroy due to shutdown | ||
267 | */ | ||
268 | void | ||
269 | GCCH_handle_remote_destroy (struct CadetChannel *ch, | ||
270 | const struct | ||
271 | GNUNET_CADET_ConnectionTunnelIdentifier *cti); | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Handle data given by a client. | ||
276 | * | ||
277 | * Check whether the client is allowed to send in this tunnel, save if | ||
278 | * channel is reliable and send an ACK to the client if there is still | ||
279 | * buffer space in the tunnel. | ||
280 | * | ||
281 | * @param ch Channel. | ||
282 | * @param sender_ccn ccn of the sender | ||
283 | * @param buf payload to transmit. | ||
284 | * @param buf_len number of bytes in @a buf | ||
285 | * @return #GNUNET_OK if everything goes well, | ||
286 | * #GNUNET_SYSERR in case of an error. | ||
287 | */ | ||
288 | int | ||
289 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
290 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
291 | const char *buf, | ||
292 | size_t buf_len); | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Handle ACK from client on local channel. Means the client is ready | ||
297 | * for more data, see if we have any for it. | ||
298 | * | ||
299 | * @param ch channel to destroy | ||
300 | * @param client_ccn ccn of the client sending the ack | ||
301 | */ | ||
302 | void | ||
303 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
304 | struct GNUNET_CADET_ClientChannelNumber client_ccn); | ||
305 | |||
306 | #endif | ||
diff --git a/src/service/cadet/gnunet-service-cadet_connection.c b/src/service/cadet/gnunet-service-cadet_connection.c new file mode 100644 index 000000000..f01c1388e --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_connection.c | |||
@@ -0,0 +1,1079 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.c | ||
23 | * @brief management of CORE-level end-to-end connections; establishes | ||
24 | * end-to-end routes and transmits messages along the route | ||
25 | * @author Bartlomiej Polot | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_signatures.h" | ||
30 | #include "gnunet-service-cadet_connection.h" | ||
31 | #include "gnunet-service-cadet_channel.h" | ||
32 | #include "gnunet-service-cadet_paths.h" | ||
33 | #include "gnunet-service-cadet_tunnels.h" | ||
34 | #include "gnunet_cadet_service.h" | ||
35 | #include "gnunet_statistics_service.h" | ||
36 | #include "cadet_protocol.h" | ||
37 | |||
38 | |||
39 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-con", __VA_ARGS__) | ||
40 | |||
41 | |||
42 | /** | ||
43 | * How long do we wait initially before retransmitting the KX? | ||
44 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! | ||
45 | */ | ||
46 | #define INITIAL_CONNECTION_CREATE_RETRY_DELAY \ | ||
47 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
48 | |||
49 | |||
50 | /** | ||
51 | * All the states a connection can be in. | ||
52 | */ | ||
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 cid. | ||
435 | * | ||
436 | * @param cid connection identifier where we got an ACK for a message | ||
437 | * that was originally sent via this connection (the ACK | ||
438 | * may have gotten back to us via a different connection). | ||
439 | */ | ||
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 | void | ||
453 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
454 | struct GNUNET_TIME_Relative latency) | ||
455 | { | ||
456 | struct CadetConnection *cc; | ||
457 | double weight; | ||
458 | double result; | ||
459 | |||
460 | cc = GCC_lookup (cid); | ||
461 | if (NULL == cc) | ||
462 | return; /* whopise, connection already down? */ | ||
463 | GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO); | ||
464 | cc->latency_datapoints++; | ||
465 | if (cc->latency_datapoints >= 7) | ||
466 | weight = 7.0; | ||
467 | else | ||
468 | weight = cc->latency_datapoints; | ||
469 | /* Compute weighted average, giving at MOST weight 7 to the | ||
470 | existing values, or less if that value is based on fewer than 7 | ||
471 | measurements. */ | ||
472 | result = (weight * cc->metrics.aged_latency.rel_value_us) | ||
473 | + 1.0 * latency.rel_value_us; | ||
474 | result /= (weight + 1.0); | ||
475 | cc->metrics.aged_latency.rel_value_us = (uint64_t) result; | ||
476 | } | ||
477 | |||
478 | |||
479 | void | ||
480 | GCC_handle_connection_create_ack (struct CadetConnection *cc) | ||
481 | { | ||
482 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
483 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", | ||
484 | GCC_2s (cc), | ||
485 | cc->state, | ||
486 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
487 | if (CADET_CONNECTION_READY == cc->state) | ||
488 | return; /* Duplicate ACK, ignore */ | ||
489 | if (NULL != cc->task) | ||
490 | { | ||
491 | GNUNET_SCHEDULER_cancel (cc->task); | ||
492 | cc->task = NULL; | ||
493 | } | ||
494 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
495 | update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready); | ||
496 | if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) && | ||
497 | (NULL == cc->task)) | ||
498 | cc->task = | ||
499 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
500 | } | ||
501 | |||
502 | |||
503 | /** | ||
504 | * Handle KX message. | ||
505 | * | ||
506 | * @param cc connection that received encrypted message | ||
507 | * @param msg the key exchange message | ||
508 | */ | ||
509 | void | ||
510 | GCC_handle_kx (struct CadetConnection *cc, | ||
511 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
512 | { | ||
513 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
514 | "Received KX message with ephermal %s on CC %s in state %d\n", | ||
515 | GNUNET_e2s (&msg->ephemeral_key), | ||
516 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
517 | cc->state); | ||
518 | if (CADET_CONNECTION_SENT == cc->state) | ||
519 | { | ||
520 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
521 | clearly something is working, so pretend we got an ACK. */ | ||
522 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
523 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
524 | GCC_2s (cc)); | ||
525 | GCC_handle_connection_create_ack (cc); | ||
526 | } | ||
527 | GCT_handle_kx (cc->ct, msg); | ||
528 | } | ||
529 | |||
530 | |||
531 | /** | ||
532 | * Handle KX_AUTH message. | ||
533 | * | ||
534 | * @param cc connection that received encrypted message | ||
535 | * @param msg the key exchange message | ||
536 | */ | ||
537 | void | ||
538 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
539 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
540 | { | ||
541 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
542 | "Received KX AUTH message with ephermal %s on CC %s in state %d\n", | ||
543 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
544 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
545 | cc->state); | ||
546 | if (CADET_CONNECTION_SENT == cc->state) | ||
547 | { | ||
548 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
549 | clearly something is working, so pretend we got an ACK. */ | ||
550 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
551 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
552 | GCC_2s (cc)); | ||
553 | GCC_handle_connection_create_ack (cc); | ||
554 | } | ||
555 | GCT_handle_kx_auth (cc->ct, msg); | ||
556 | } | ||
557 | |||
558 | |||
559 | /** | ||
560 | * Handle encrypted message. | ||
561 | * | ||
562 | * @param cc connection that received encrypted message | ||
563 | * @param msg the encrypted message to decrypt | ||
564 | */ | ||
565 | void | ||
566 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
567 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
568 | { | ||
569 | if (CADET_CONNECTION_SENT == cc->state) | ||
570 | { | ||
571 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
572 | clearly something is working, so pretend we got an ACK. */ | ||
573 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
574 | "Faking connection ACK for %s due to ENCRYPTED payload\n", | ||
575 | GCC_2s (cc)); | ||
576 | GCC_handle_connection_create_ack (cc); | ||
577 | } | ||
578 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
579 | GCT_handle_encrypted (cc->ct, msg); | ||
580 | } | ||
581 | |||
582 | |||
583 | /** | ||
584 | * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage. | ||
585 | * | ||
586 | * @param msg The GNUNET_CADET_ConnectionCreateMessage. | ||
587 | */ | ||
588 | void | ||
589 | set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
590 | { | ||
591 | |||
592 | struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl ( | ||
593 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR), | ||
594 | .purpose.size = htonl (sizeof(cp)), | ||
595 | .monotonic_time = msg->monotime}; | ||
596 | |||
597 | GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp, | ||
598 | &msg->monotime_sig); | ||
599 | |||
600 | } | ||
601 | |||
602 | |||
603 | /** | ||
604 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the | ||
605 | * first hop. | ||
606 | * | ||
607 | * @param cls the `struct CadetConnection` to initiate | ||
608 | */ | ||
609 | static void | ||
610 | send_create (void *cls) | ||
611 | { | ||
612 | struct CadetConnection *cc = cls; | ||
613 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
614 | struct GNUNET_PeerIdentity *pids; | ||
615 | struct GNUNET_MQ_Envelope *env; | ||
616 | struct CadetTunnel *t; | ||
617 | |||
618 | cc->task = NULL; | ||
619 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
620 | env = | ||
621 | GNUNET_MQ_msg_extra (create_msg, | ||
622 | (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity), | ||
623 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
624 | // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed. | ||
625 | create_msg->options = 2; | ||
626 | create_msg->cid = cc->cid; | ||
627 | |||
628 | // check for tunnel state and set signed monotime (xrs,t3ss) | ||
629 | t = GCP_get_tunnel (cc->destination, GNUNET_YES); | ||
630 | if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) && | ||
631 | (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO)) | ||
632 | { | ||
633 | create_msg->has_monotime = GNUNET_YES; | ||
634 | create_msg->monotime = GNUNET_TIME_absolute_hton ( | ||
635 | GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
636 | set_monotime_sig (create_msg); | ||
637 | } | ||
638 | |||
639 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
640 | pids[0] = my_full_id; | ||
641 | for (unsigned int i = 0; i <= cc->off; i++) | ||
642 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i)); | ||
643 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
644 | "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n", | ||
645 | GCC_2s (cc), | ||
646 | cc->off + 2); | ||
647 | cc->env = env; | ||
648 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
649 | cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); | ||
650 | update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO); | ||
651 | GCP_send (cc->mq_man, env); | ||
652 | } | ||
653 | |||
654 | |||
655 | /** | ||
656 | * Send a CREATE_ACK message towards the origin. | ||
657 | * | ||
658 | * @param cls the `struct CadetConnection` to initiate | ||
659 | */ | ||
660 | static void | ||
661 | send_create_ack (void *cls) | ||
662 | { | ||
663 | struct CadetConnection *cc = cls; | ||
664 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; | ||
665 | struct GNUNET_MQ_Envelope *env; | ||
666 | |||
667 | cc->task = NULL; | ||
668 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
669 | "Sending CONNECTION_CREATE_ACK message for %s\n", | ||
670 | GCC_2s (cc)); | ||
671 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
672 | env = | ||
673 | GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); | ||
674 | ack_msg->cid = cc->cid; | ||
675 | cc->env = env; | ||
676 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
677 | cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); | ||
678 | if (CADET_CONNECTION_CREATE_RECEIVED == cc->state) | ||
679 | update_state (cc, CADET_CONNECTION_READY, GNUNET_NO); | ||
680 | if (CADET_CONNECTION_READY == cc->state) | ||
681 | cc->task = | ||
682 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
683 | GCP_send (cc->mq_man, env); | ||
684 | } | ||
685 | |||
686 | |||
687 | /** | ||
688 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
689 | * connection that we already have. Either our ACK got lost | ||
690 | * or something is fishy. Consider retransmitting the ACK. | ||
691 | * | ||
692 | * @param cc connection that got the duplicate CREATE | ||
693 | */ | ||
694 | void | ||
695 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
696 | { | ||
697 | if (GNUNET_YES == cc->mqm_ready) | ||
698 | { | ||
699 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
700 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", | ||
701 | GCC_2s (cc), | ||
702 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
703 | /* Revert back to the state of having only received the 'CREATE', | ||
704 | and immediately proceed to send the CREATE_ACK. */ | ||
705 | update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready); | ||
706 | if (NULL != cc->task) | ||
707 | GNUNET_SCHEDULER_cancel (cc->task); | ||
708 | cc->task = | ||
709 | GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc); | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | /* We are currently sending something else back, which | ||
714 | can only be an ACK or payload, either of which would | ||
715 | do. So actually no need to do anything. */ | ||
716 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
717 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", | ||
718 | GCC_2s (cc)); | ||
719 | } | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
724 | * There has been a change in the message queue existence for our | ||
725 | * peer at the first hop. Adjust accordingly. | ||
726 | * | ||
727 | * @param cls the `struct CadetConnection` | ||
728 | * @param available #GNUNET_YES if sending is now possible, | ||
729 | * #GNUNET_NO if sending is no longer possible | ||
730 | * #GNUNET_SYSERR if sending is no longer possible | ||
731 | * and the last envelope was discarded | ||
732 | */ | ||
733 | static void | ||
734 | manage_first_hop_mq (void *cls, int available) | ||
735 | { | ||
736 | struct CadetConnection *cc = cls; | ||
737 | |||
738 | if (GNUNET_YES != available) | ||
739 | { | ||
740 | /* Connection is down, for now... */ | ||
741 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc)); | ||
742 | update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO); | ||
743 | cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY; | ||
744 | if (NULL != cc->task) | ||
745 | { | ||
746 | GNUNET_SCHEDULER_cancel (cc->task); | ||
747 | cc->task = NULL; | ||
748 | } | ||
749 | return; | ||
750 | } | ||
751 | |||
752 | update_state (cc, cc->state, GNUNET_YES); | ||
753 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
754 | "Core MQ for %s became available in state %d\n", | ||
755 | GCC_2s (cc), | ||
756 | cc->state); | ||
757 | switch (cc->state) | ||
758 | { | ||
759 | case CADET_CONNECTION_NEW: | ||
760 | /* Transmit immediately */ | ||
761 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc); | ||
762 | break; | ||
763 | |||
764 | case CADET_CONNECTION_SENDING_CREATE: | ||
765 | /* Should not be possible to be called in this state. */ | ||
766 | GNUNET_assert (0); | ||
767 | break; | ||
768 | |||
769 | case CADET_CONNECTION_SENT: | ||
770 | /* Retry a bit later... */ | ||
771 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc); | ||
772 | break; | ||
773 | |||
774 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
775 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
776 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
777 | cc->task = | ||
778 | GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc); | ||
779 | break; | ||
780 | |||
781 | case CADET_CONNECTION_READY: | ||
782 | if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) && | ||
783 | (NULL == cc->task)) | ||
784 | { | ||
785 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
786 | "Scheduling keepalive for %s in %s\n", | ||
787 | GCC_2s (cc), | ||
788 | GNUNET_STRINGS_relative_time_to_string (keepalive_period, | ||
789 | GNUNET_YES)); | ||
790 | cc->task = | ||
791 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
792 | } | ||
793 | break; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | |||
798 | /** | ||
799 | * Create a connection to @a destination via @a path and notify @a cb | ||
800 | * whenever we are ready for more data. Shared logic independent of | ||
801 | * who is initiating the connection. | ||
802 | * | ||
803 | * @param destination where to go | ||
804 | * @param path which path to take (may not be the full path) | ||
805 | * @param off offset of @a destination on @a path | ||
806 | * @param ct which tunnel uses this connection | ||
807 | * @param init_state initial state for the connection | ||
808 | * @param ready_cb function to call when ready to transmit | ||
809 | * @param ready_cb_cls closure for @a cb | ||
810 | * @return handle to the connection | ||
811 | */ | ||
812 | static struct CadetConnection * | ||
813 | connection_create (struct CadetPeer *destination, | ||
814 | struct CadetPeerPath *path, | ||
815 | unsigned int off, | ||
816 | struct CadetTConnection *ct, | ||
817 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
818 | enum CadetConnectionState init_state, | ||
819 | GCC_ReadyCallback ready_cb, | ||
820 | void *ready_cb_cls) | ||
821 | { | ||
822 | struct CadetConnection *cc; | ||
823 | struct CadetPeer *first_hop; | ||
824 | |||
825 | cc = GNUNET_new (struct CadetConnection); | ||
826 | cc->state = init_state; | ||
827 | cc->ct = ct; | ||
828 | cc->destination = destination; /* xrs,t3ss,lurchi*/ | ||
829 | cc->cid = *cid; | ||
830 | cc->retry_delay = | ||
831 | GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off); | ||
832 | GNUNET_assert (GNUNET_OK == | ||
833 | GNUNET_CONTAINER_multishortmap_put ( | ||
834 | connections, | ||
835 | &GCC_get_id (cc)->connection_of_tunnel, | ||
836 | cc, | ||
837 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
838 | cc->ready_cb = ready_cb; | ||
839 | cc->ready_cb_cls = ready_cb_cls; | ||
840 | cc->path = path; | ||
841 | cc->off = off; | ||
842 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
843 | "Creating %s using path %s (offset: %u)\n", | ||
844 | GCC_2s (cc), | ||
845 | GCPP_2s (path), | ||
846 | off); | ||
847 | GCPP_add_connection (path, off, cc); | ||
848 | for (unsigned int i = 0; i < off; i++) | ||
849 | GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc); | ||
850 | first_hop = GCPP_get_peer_at_offset (path, 0); | ||
851 | cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc); | ||
852 | return cc; | ||
853 | } | ||
854 | |||
855 | |||
856 | /** | ||
857 | * Create a connection to @a destination via @a path and | ||
858 | * notify @a cb whenever we are ready for more data. This | ||
859 | * is an inbound tunnel, so we must use the existing @a cid | ||
860 | * | ||
861 | * @param destination where to go | ||
862 | * @param path which path to take (may not be the full path) | ||
863 | * @param ct which tunnel uses this connection | ||
864 | * @param ready_cb function to call when ready to transmit | ||
865 | * @param ready_cb_cls closure for @a cb | ||
866 | * @return handle to the connection, NULL if we already have | ||
867 | * a connection that takes precedence on @a path | ||
868 | */ | ||
869 | struct CadetConnection * | ||
870 | GCC_create_inbound (struct CadetPeer *destination, | ||
871 | struct CadetPeerPath *path, | ||
872 | struct CadetTConnection *ct, | ||
873 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
874 | GCC_ReadyCallback ready_cb, | ||
875 | void *ready_cb_cls) | ||
876 | { | ||
877 | struct CadetConnection *cc; | ||
878 | unsigned int off; | ||
879 | |||
880 | off = GCPP_find_peer (path, destination); | ||
881 | GNUNET_assert (UINT_MAX != off); | ||
882 | cc = GCPP_get_connection (path, destination, off); | ||
883 | if (NULL != cc) | ||
884 | { | ||
885 | int cmp; | ||
886 | |||
887 | cmp = GNUNET_memcmp (cid, &cc->cid); | ||
888 | if (0 == cmp) | ||
889 | { | ||
890 | /* Two peers picked the SAME random connection identifier at the | ||
891 | same time for the same path? Must be malicious. Drop | ||
892 | connection (existing and inbound), even if it is the only | ||
893 | one. */ | ||
894 | GNUNET_break_op (0); | ||
895 | GCT_connection_lost (cc->ct); | ||
896 | GCC_destroy_without_tunnel (cc); | ||
897 | return NULL; | ||
898 | } | ||
899 | if (0 < cmp) | ||
900 | { | ||
901 | /* drop existing */ | ||
902 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
903 | "Got two connections on %s, dropping my existing %s\n", | ||
904 | GCPP_2s (path), | ||
905 | GCC_2s (cc)); | ||
906 | GCT_connection_lost (cc->ct); | ||
907 | GCC_destroy_without_tunnel (cc); | ||
908 | } | ||
909 | else | ||
910 | { | ||
911 | /* keep existing */ | ||
912 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
913 | "Got two connections on %s, keeping my existing %s\n", | ||
914 | GCPP_2s (path), | ||
915 | GCC_2s (cc)); | ||
916 | return NULL; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | return connection_create (destination, | ||
921 | path, | ||
922 | off, | ||
923 | ct, | ||
924 | cid, | ||
925 | CADET_CONNECTION_CREATE_RECEIVED, | ||
926 | ready_cb, | ||
927 | ready_cb_cls); | ||
928 | } | ||
929 | |||
930 | |||
931 | struct CadetConnection * | ||
932 | GCC_create (struct CadetPeer *destination, | ||
933 | struct CadetPeerPath *path, | ||
934 | unsigned int off, | ||
935 | struct CadetTConnection *ct, | ||
936 | GCC_ReadyCallback ready_cb, | ||
937 | void *ready_cb_cls) | ||
938 | { | ||
939 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
940 | |||
941 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid)); | ||
942 | return connection_create (destination, | ||
943 | path, | ||
944 | off, | ||
945 | ct, | ||
946 | &cid, | ||
947 | CADET_CONNECTION_NEW, | ||
948 | ready_cb, | ||
949 | ready_cb_cls); | ||
950 | } | ||
951 | |||
952 | |||
953 | /** | ||
954 | * Transmit message @a msg via connection @a cc. Must only be called | ||
955 | * (once) after the connection has signalled that it is ready via the | ||
956 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
957 | * connection is right now ready for transmission. | ||
958 | * | ||
959 | * @param cc connection identification | ||
960 | * @param env envelope with message to transmit; must NOT | ||
961 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
962 | */ | ||
963 | void | ||
964 | GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env) | ||
965 | { | ||
966 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
967 | "Scheduling message for transmission on %s\n", | ||
968 | GCC_2s (cc)); | ||
969 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
970 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); | ||
971 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
972 | cc->mqm_ready = GNUNET_NO; | ||
973 | if (NULL != cc->task) | ||
974 | { | ||
975 | GNUNET_SCHEDULER_cancel (cc->task); | ||
976 | cc->task = NULL; | ||
977 | } | ||
978 | GCP_send (cc->mq_man, env); | ||
979 | } | ||
980 | |||
981 | |||
982 | /** | ||
983 | * Obtain the path used by this connection. | ||
984 | * | ||
985 | * @param cc connection | ||
986 | * @param[out] off set to the length of the path we use | ||
987 | * @return path to @a cc | ||
988 | */ | ||
989 | struct CadetPeerPath * | ||
990 | GCC_get_path (struct CadetConnection *cc, unsigned int *off) | ||
991 | { | ||
992 | *off = cc->off; | ||
993 | return cc->path; | ||
994 | } | ||
995 | |||
996 | |||
997 | /** | ||
998 | * Obtain unique ID for the connection. | ||
999 | * | ||
1000 | * @param cc connection. | ||
1001 | * @return unique number of the connection | ||
1002 | */ | ||
1003 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
1004 | GCC_get_id (struct CadetConnection *cc) | ||
1005 | { | ||
1006 | return &cc->cid; | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * Get a (static) string for a connection. | ||
1012 | * | ||
1013 | * @param cc Connection. | ||
1014 | */ | ||
1015 | const char * | ||
1016 | GCC_2s (const struct CadetConnection *cc) | ||
1017 | { | ||
1018 | static char buf[128]; | ||
1019 | |||
1020 | if (NULL == cc) | ||
1021 | return "Connection(NULL)"; | ||
1022 | |||
1023 | if (NULL != cc->ct) | ||
1024 | { | ||
1025 | GNUNET_snprintf (buf, | ||
1026 | sizeof(buf), | ||
1027 | "Connection %s (%s)", | ||
1028 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
1029 | GCT_2s (cc->ct->t)); | ||
1030 | return buf; | ||
1031 | } | ||
1032 | GNUNET_snprintf (buf, | ||
1033 | sizeof(buf), | ||
1034 | "Connection %s", | ||
1035 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
1036 | return buf; | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | #define LOG2(level, ...) \ | ||
1041 | GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__) | ||
1042 | |||
1043 | |||
1044 | /** | ||
1045 | * Log connection info. | ||
1046 | * | ||
1047 | * @param cc connection | ||
1048 | * @param level Debug level to use. | ||
1049 | */ | ||
1050 | void | ||
1051 | GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level) | ||
1052 | { | ||
1053 | #if ! defined(GNUNET_CULL_LOGGING) | ||
1054 | int do_log; | ||
1055 | |||
1056 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1057 | "cadet-con", | ||
1058 | __FILE__, | ||
1059 | __FUNCTION__, | ||
1060 | __LINE__); | ||
1061 | if (0 == do_log) | ||
1062 | return; | ||
1063 | if (NULL == cc) | ||
1064 | { | ||
1065 | LOG2 (level, "Connection (NULL)\n"); | ||
1066 | return; | ||
1067 | } | ||
1068 | LOG2 (level, | ||
1069 | "%s to %s via path %s in state %d is %s\n", | ||
1070 | GCC_2s (cc), | ||
1071 | GCP_2s (cc->destination), | ||
1072 | GCPP_2s (cc->path), | ||
1073 | cc->state, | ||
1074 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
1075 | #endif | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /* end of gnunet-service-cadet_connection.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_connection.h b/src/service/cadet/gnunet-service-cadet_connection.h new file mode 100644 index 000000000..54c845b13 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_connection.h | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.h | ||
23 | * @brief A connection is a live end-to-end messaging mechanism | ||
24 | * where the peers are identified by a path and know how | ||
25 | * to forward along the route using a connection identifier | ||
26 | * for routing the data. | ||
27 | * @author Bartlomiej Polot | ||
28 | * @author Christian Grothoff | ||
29 | */ | ||
30 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H | ||
31 | #define GNUNET_SERVICE_CADET_CONNECTION_H | ||
32 | |||
33 | #include "gnunet_util_lib.h" | ||
34 | #include "gnunet-service-cadet.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | #include "cadet_protocol.h" | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Function called to notify tunnel about change in our readiness. | ||
41 | * | ||
42 | * @param cls closure | ||
43 | * @param is_ready #GNUNET_YES if the connection is now ready for transmission, | ||
44 | * #GNUNET_NO if the connection is no longer ready for transmission | ||
45 | */ | ||
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 #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for | ||
146 | * this connection, implying that the end-to-end connection is up. | ||
147 | * Process it. | ||
148 | * | ||
149 | * @param cc the connection that got the ACK. | ||
150 | */ | ||
151 | void | ||
152 | GCC_handle_connection_create_ack (struct CadetConnection *cc); | ||
153 | |||
154 | |||
155 | /** | ||
156 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
157 | * connection that we already have. Either our ACK got lost | ||
158 | * or something is fishy. Consider retransmitting the ACK. | ||
159 | * | ||
160 | * @param cc connection that got the duplicate CREATE | ||
161 | */ | ||
162 | void | ||
163 | GCC_handle_duplicate_create (struct CadetConnection *cc); | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Handle KX message. | ||
168 | * | ||
169 | * @param cc connection that received encrypted message | ||
170 | * @param msg the key exchange message | ||
171 | */ | ||
172 | void | ||
173 | GCC_handle_kx (struct CadetConnection *cc, | ||
174 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
175 | |||
176 | |||
177 | /** | ||
178 | * Handle KX_AUTH message. | ||
179 | * | ||
180 | * @param cc connection that received encrypted message | ||
181 | * @param msg the key exchange message | ||
182 | */ | ||
183 | void | ||
184 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
185 | const struct | ||
186 | GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
187 | |||
188 | /** | ||
189 | * Purpose for the signature of a monotime. | ||
190 | */ | ||
191 | struct CadetConnectionCreatePS | ||
192 | { | ||
193 | |||
194 | /** | ||
195 | * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR | ||
196 | */ | ||
197 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
198 | |||
199 | /** | ||
200 | * Time at the initiator when generating the signature. | ||
201 | * | ||
202 | * Note that the receiver MUST IGNORE the absolute time, and only interpret | ||
203 | * the value as a mononic time and reject "older" values than the last one | ||
204 | * observed. This is necessary as we do not want to require synchronized | ||
205 | * clocks and may not have a bidirectional communication channel. | ||
206 | * | ||
207 | * Even with this, there is no real guarantee against replay achieved here, | ||
208 | * unless the latest timestamp is persisted. Persistence should be | ||
209 | * provided via PEERSTORE if possible. | ||
210 | */ | ||
211 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | ||
212 | |||
213 | }; | ||
214 | |||
215 | /** | ||
216 | * Performance metrics for a connection. | ||
217 | */ | ||
218 | struct CadetConnectionMetrics | ||
219 | { | ||
220 | /** | ||
221 | * Our current best estimate of the latency, based on a weighted | ||
222 | * average of at least @a latency_datapoints values. | ||
223 | */ | ||
224 | struct GNUNET_TIME_Relative aged_latency; | ||
225 | |||
226 | /** | ||
227 | * When was this connection first established? (by us sending or | ||
228 | * receiving the CREATE_ACK for the first time) | ||
229 | */ | ||
230 | struct GNUNET_TIME_Absolute age; | ||
231 | |||
232 | /** | ||
233 | * When was this connection last used? (by us sending or | ||
234 | * receiving a PAYLOAD message on it) | ||
235 | */ | ||
236 | struct GNUNET_TIME_Absolute last_use; | ||
237 | |||
238 | /** | ||
239 | * How many packets that ought to generate an ACK did we send via | ||
240 | * this connection? | ||
241 | */ | ||
242 | unsigned long long num_acked_transmissions; | ||
243 | |||
244 | /** | ||
245 | * Number of packets that were sent via this connection did actually | ||
246 | * receive an ACK? (Note: ACKs may be transmitted and lost via | ||
247 | * other connections, so this value should only be interpreted | ||
248 | * relative to @e num_acked_transmissions and in relation to other | ||
249 | * connections.) | ||
250 | */ | ||
251 | unsigned long long num_successes; | ||
252 | }; | ||
253 | |||
254 | |||
255 | /** | ||
256 | * Obtain performance @a metrics from @a cc. | ||
257 | * | ||
258 | * @param cc connection to query | ||
259 | * @return the metrics | ||
260 | */ | ||
261 | const struct CadetConnectionMetrics * | ||
262 | GCC_get_metrics (struct CadetConnection *cc); | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Handle encrypted message. | ||
267 | * | ||
268 | * @param cc connection that received encrypted message | ||
269 | * @param msg the encrypted message to decrypt | ||
270 | */ | ||
271 | void | ||
272 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
273 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
274 | |||
275 | |||
276 | /** | ||
277 | * We sent a message for which we expect to receive an ACK via | ||
278 | * the connection identified by @a cti. | ||
279 | * | ||
280 | * @param cid connection identifier where we expect an ACK | ||
281 | */ | ||
282 | void | ||
283 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * We observed an ACK for a message that was originally sent via | ||
288 | * the connection identified by @a cti. | ||
289 | * | ||
290 | * @param cid connection identifier where we got an ACK for a message | ||
291 | * that was originally sent via this connection (the ACK | ||
292 | * may have gotten back to us via a different connection). | ||
293 | */ | ||
294 | void | ||
295 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
296 | |||
297 | |||
298 | /** | ||
299 | * We observed some the given @a latency on the connection | ||
300 | * identified by @a cti. (The same connection was taken | ||
301 | * in both directions.) | ||
302 | * | ||
303 | * @param cti connection identifier where we measured latency | ||
304 | * @param latency the observed latency | ||
305 | */ | ||
306 | void | ||
307 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
308 | struct GNUNET_TIME_Relative latency); | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Return the tunnel associated with this connection. | ||
313 | * | ||
314 | * @param cc connection to query | ||
315 | * @return corresponding entry in the tunnel's connection list | ||
316 | */ | ||
317 | struct CadetTConnection * | ||
318 | GCC_get_ct (struct CadetConnection *cc); | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Obtain the path used by this connection. | ||
323 | * | ||
324 | * @param cc connection | ||
325 | * @param[out] off set to offset in this path where the connection @a cc ends | ||
326 | * @return path to @a cc | ||
327 | */ | ||
328 | struct CadetPeerPath * | ||
329 | GCC_get_path (struct CadetConnection *cc, | ||
330 | unsigned int *off); | ||
331 | |||
332 | |||
333 | /** | ||
334 | * Obtain unique ID for the connection. | ||
335 | * | ||
336 | * @param cc connection. | ||
337 | * @return unique number of the connection | ||
338 | */ | ||
339 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
340 | GCC_get_id (struct CadetConnection *cc); | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Get a (static) string for a connection. | ||
345 | * | ||
346 | * @param cc Connection. | ||
347 | */ | ||
348 | const char * | ||
349 | GCC_2s (const struct CadetConnection *cc); | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Log connection info. | ||
354 | * | ||
355 | * @param cc connection | ||
356 | * @param level Debug level to use. | ||
357 | */ | ||
358 | void | ||
359 | GCC_debug (struct CadetConnection *cc, | ||
360 | enum GNUNET_ErrorType level); | ||
361 | |||
362 | |||
363 | #endif | ||
diff --git a/src/service/cadet/gnunet-service-cadet_core.c b/src/service/cadet/gnunet-service-cadet_core.c new file mode 100644 index 000000000..68f7405c3 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_core.c | |||
@@ -0,0 +1,1337 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_core.c | ||
23 | * @brief cadet service; interaction with CORE service | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) | ||
28 | * | ||
29 | * TODO: | ||
30 | * - Optimization: given BROKEN messages, destroy paths (?) | ||
31 | */ | ||
32 | #include "platform.h" | ||
33 | #include "gnunet-service-cadet_core.h" | ||
34 | #include "gnunet-service-cadet_paths.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | #include "gnunet-service-cadet_connection.h" | ||
37 | #include "gnunet-service-cadet_tunnels.h" | ||
38 | #include "gnunet_core_service.h" | ||
39 | #include "gnunet_statistics_service.h" | ||
40 | #include "cadet_protocol.h" | ||
41 | |||
42 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-cor", __VA_ARGS__) | ||
43 | |||
44 | /** | ||
45 | * Information we keep per direction for a route. | ||
46 | */ | ||
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 | struct CadetRoute | ||
143 | { | ||
144 | /** | ||
145 | * Information about the next hop on this route. | ||
146 | */ | ||
147 | struct RouteDirection next; | ||
148 | |||
149 | /** | ||
150 | * Information about the previous hop on this route. | ||
151 | */ | ||
152 | struct RouteDirection prev; | ||
153 | |||
154 | /** | ||
155 | * Unique identifier for the connection that uses this route. | ||
156 | */ | ||
157 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
158 | |||
159 | /** | ||
160 | * When was this route last in use? | ||
161 | */ | ||
162 | struct GNUNET_TIME_Absolute last_use; | ||
163 | |||
164 | /** | ||
165 | * Position of this route in the #route_heap. | ||
166 | */ | ||
167 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
168 | }; | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Handle to the CORE service. | ||
173 | */ | ||
174 | static struct GNUNET_CORE_Handle *core; | ||
175 | |||
176 | /** | ||
177 | * Routes on which this peer is an intermediate. | ||
178 | */ | ||
179 | static struct GNUNET_CONTAINER_MultiShortmap *routes; | ||
180 | |||
181 | /** | ||
182 | * Heap of routes, MIN-sorted by last activity. | ||
183 | */ | ||
184 | static struct GNUNET_CONTAINER_Heap *route_heap; | ||
185 | |||
186 | /** | ||
187 | * Rung zero (always pointed to by #rung_head). | ||
188 | */ | ||
189 | static struct Rung rung_zero; | ||
190 | |||
191 | /** | ||
192 | * DLL of rungs, with the head always point to a rung of | ||
193 | * route directions with no messages in the queue. | ||
194 | */ | ||
195 | static struct Rung *rung_head = &rung_zero; | ||
196 | |||
197 | /** | ||
198 | * Tail of the #rung_head DLL. | ||
199 | */ | ||
200 | static struct Rung *rung_tail = &rung_zero; | ||
201 | |||
202 | /** | ||
203 | * Maximum number of concurrent routes this peer will support. | ||
204 | */ | ||
205 | static unsigned long long max_routes; | ||
206 | |||
207 | /** | ||
208 | * Maximum number of envelopes we will buffer at this peer. | ||
209 | */ | ||
210 | static unsigned long long max_buffers; | ||
211 | |||
212 | /** | ||
213 | * Current number of envelopes we have buffered at this peer. | ||
214 | */ | ||
215 | static unsigned long long cur_buffers; | ||
216 | |||
217 | /** | ||
218 | * Task to timeout routes. | ||
219 | */ | ||
220 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
221 | |||
222 | /** | ||
223 | * Get the route corresponding to a hash. | ||
224 | * | ||
225 | * @param cid hash generated from the connection identifier | ||
226 | */ | ||
227 | static struct CadetRoute * | ||
228 | get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
229 | { | ||
230 | return GNUNET_CONTAINER_multishortmap_get (routes, | ||
231 | &cid->connection_of_tunnel); | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Lower the rung in which @a dir is by 1. | ||
237 | * | ||
238 | * @param dir direction to lower in rung. | ||
239 | */ | ||
240 | static void | ||
241 | lower_rung (struct RouteDirection *dir) | ||
242 | { | ||
243 | struct Rung *rung = dir->rung; | ||
244 | struct Rung *prev; | ||
245 | |||
246 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
247 | prev = rung->prev; | ||
248 | GNUNET_assert (NULL != prev); | ||
249 | if (prev->rung_off != rung->rung_off - 1) | ||
250 | { | ||
251 | prev = GNUNET_new (struct Rung); | ||
252 | prev->rung_off = rung->rung_off - 1; | ||
253 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev); | ||
254 | } | ||
255 | GNUNET_assert (NULL != prev); | ||
256 | GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir); | ||
257 | dir->rung = prev; | ||
258 | } | ||
259 | |||
260 | |||
261 | /** | ||
262 | * Discard the buffer @a env from the route direction @a dir and | ||
263 | * move @a dir down a rung. | ||
264 | * | ||
265 | * @param dir direction that contains the @a env in the buffer | ||
266 | * @param env envelope to discard | ||
267 | */ | ||
268 | static void | ||
269 | discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env) | ||
270 | { | ||
271 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
272 | cur_buffers--; | ||
273 | GNUNET_MQ_discard (env); | ||
274 | lower_rung (dir); | ||
275 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Discard all messages from the highest rung, to make space. | ||
281 | */ | ||
282 | static void | ||
283 | discard_all_from_rung_tail () | ||
284 | { | ||
285 | struct Rung *tail = rung_tail; | ||
286 | struct RouteDirection *dir; | ||
287 | |||
288 | while (NULL != (dir = tail->rd_head)) | ||
289 | { | ||
290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
291 | "Queue full due new message on connection %s, dropping old message\n", | ||
292 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
293 | GNUNET_STATISTICS_update (stats, | ||
294 | "# messages dropped due to full buffer", | ||
295 | 1, | ||
296 | GNUNET_NO); | ||
297 | discard_buffer (dir, dir->env_head); | ||
298 | } | ||
299 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail); | ||
300 | GNUNET_free (tail); | ||
301 | } | ||
302 | |||
303 | |||
304 | /** | ||
305 | * We message @a msg from @a prev. Find its route by @a cid and | ||
306 | * forward to the next hop. Drop and signal broken route if we do not | ||
307 | * have a route. | ||
308 | * | ||
309 | * @param prev previous hop (sender) | ||
310 | * @param cid connection identifier, tells us which route to use | ||
311 | * @param msg the message to forward | ||
312 | */ | ||
313 | static void | ||
314 | route_message (struct CadetPeer *prev, | ||
315 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
316 | const struct GNUNET_MessageHeader *msg, | ||
317 | const enum GNUNET_MQ_PriorityPreferences priority) | ||
318 | { | ||
319 | struct CadetRoute *route; | ||
320 | struct RouteDirection *dir; | ||
321 | struct Rung *rung; | ||
322 | struct Rung *nxt; | ||
323 | struct GNUNET_MQ_Envelope *env; | ||
324 | |||
325 | route = get_route (cid); | ||
326 | if (NULL == route) | ||
327 | { | ||
328 | struct GNUNET_MQ_Envelope *env; | ||
329 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
330 | |||
331 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
332 | "Failed to route message of type %u from %s on connection %s: no route\n", | ||
333 | ntohs (msg->type), | ||
334 | GCP_2s (prev), | ||
335 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
336 | switch (ntohs (msg->type)) | ||
337 | { | ||
338 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
339 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
340 | /* No need to respond to these! */ | ||
341 | return; | ||
342 | } | ||
343 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
344 | bm->cid = *cid; | ||
345 | bm->peer1 = my_full_id; | ||
346 | GCP_send_ooo (prev, env); | ||
347 | return; | ||
348 | } | ||
349 | route->last_use = GNUNET_TIME_absolute_get (); | ||
350 | GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us); | ||
351 | dir = (prev == route->prev.hop) ? &route->next : &route->prev; | ||
352 | if (GNUNET_YES == dir->is_ready) | ||
353 | { | ||
354 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
355 | "Routing message of type %u from %s to %s on connection %s\n", | ||
356 | ntohs (msg->type), | ||
357 | GCP_2s (prev), | ||
358 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
359 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
360 | dir->is_ready = GNUNET_NO; | ||
361 | GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg)); | ||
362 | return; | ||
363 | } | ||
364 | /* Check if low latency is required and if the previous message was | ||
365 | unreliable; if so, make sure we only queue one message per | ||
366 | direction (no buffering). */ | ||
367 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
368 | (NULL != dir->env_head) && | ||
369 | (0 == | ||
370 | (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE))) | ||
371 | discard_buffer (dir, dir->env_head); | ||
372 | /* Check for duplicates */ | ||
373 | for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env; | ||
374 | env = GNUNET_MQ_env_next (env)) | ||
375 | { | ||
376 | const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env); | ||
377 | |||
378 | if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size)))) | ||
379 | { | ||
380 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
381 | "Received duplicate of message already in buffer, dropping\n"); | ||
382 | GNUNET_STATISTICS_update (stats, | ||
383 | "# messages dropped due to duplicate in buffer", | ||
384 | 1, | ||
385 | GNUNET_NO); | ||
386 | return; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | rung = dir->rung; | ||
391 | if (cur_buffers == max_buffers) | ||
392 | { | ||
393 | /* Need to make room. */ | ||
394 | if (NULL != rung->next) | ||
395 | { | ||
396 | /* Easy case, drop messages from route directions in highest rung */ | ||
397 | discard_all_from_rung_tail (); | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | /* We are in the highest rung, drop our own! */ | ||
402 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
403 | "Queue full due new message on connection %s, dropping old message\n", | ||
404 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
405 | GNUNET_STATISTICS_update (stats, | ||
406 | "# messages dropped due to full buffer", | ||
407 | 1, | ||
408 | GNUNET_NO); | ||
409 | discard_buffer (dir, dir->env_head); | ||
410 | rung = dir->rung; | ||
411 | } | ||
412 | } | ||
413 | /* remove 'dir' from current rung */ | ||
414 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
415 | /* make 'nxt' point to the next higher rung, create if necessary */ | ||
416 | nxt = rung->next; | ||
417 | if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off)) | ||
418 | { | ||
419 | nxt = GNUNET_new (struct Rung); | ||
420 | nxt->rung_off = rung->rung_off + 1; | ||
421 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt); | ||
422 | } | ||
423 | /* insert 'dir' into next higher rung */ | ||
424 | GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir); | ||
425 | dir->rung = nxt; | ||
426 | |||
427 | /* add message into 'dir' buffer */ | ||
428 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
429 | "Queueing new message of type %u from %s to %s on connection %s\n", | ||
430 | ntohs (msg->type), | ||
431 | GCP_2s (prev), | ||
432 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
433 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
434 | env = GNUNET_MQ_msg_copy (msg); | ||
435 | GNUNET_MQ_env_set_options (env, priority); | ||
436 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
437 | (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) && | ||
438 | (NULL != dir->env_head) && | ||
439 | (0 == (GNUNET_MQ_env_get_options (dir->env_head) | ||
440 | & GNUNET_MQ_PREF_LOW_LATENCY))) | ||
441 | GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env); | ||
442 | else | ||
443 | GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env); | ||
444 | cur_buffers++; | ||
445 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
446 | /* Clean up 'rung' if now empty (and not head) */ | ||
447 | if ((NULL == rung->rd_head) && (rung != rung_head)) | ||
448 | { | ||
449 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung); | ||
450 | GNUNET_free (rung); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | |||
455 | /** | ||
456 | * Check if the create_connection message has the appropriate size. | ||
457 | * | ||
458 | * @param cls Closure (unused). | ||
459 | * @param msg Message to check. | ||
460 | * | ||
461 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
462 | */ | ||
463 | static int | ||
464 | check_connection_create (void *cls, | ||
465 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
466 | { | ||
467 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
468 | |||
469 | if (0 != (size % sizeof(struct GNUNET_PeerIdentity))) | ||
470 | { | ||
471 | GNUNET_break_op (0); | ||
472 | return GNUNET_NO; | ||
473 | } | ||
474 | return GNUNET_YES; | ||
475 | } | ||
476 | |||
477 | |||
478 | /** | ||
479 | * Free internal data of a route direction. | ||
480 | * | ||
481 | * @param dir direction to destroy (do NOT free memory of 'dir' itself) | ||
482 | */ | ||
483 | static void | ||
484 | destroy_direction (struct RouteDirection *dir) | ||
485 | { | ||
486 | struct GNUNET_MQ_Envelope *env; | ||
487 | |||
488 | while (NULL != (env = dir->env_head)) | ||
489 | { | ||
490 | GNUNET_STATISTICS_update (stats, | ||
491 | "# messages dropped due to route destruction", | ||
492 | 1, | ||
493 | GNUNET_NO); | ||
494 | discard_buffer (dir, env); | ||
495 | } | ||
496 | if (NULL != dir->mqm) | ||
497 | { | ||
498 | GCP_request_mq_cancel (dir->mqm, NULL); | ||
499 | dir->mqm = NULL; | ||
500 | } | ||
501 | GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir); | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Destroy our state for @a route. | ||
507 | * | ||
508 | * @param route route to destroy | ||
509 | */ | ||
510 | static void | ||
511 | destroy_route (struct CadetRoute *route) | ||
512 | { | ||
513 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
514 | "Destroying route from %s to %s of connection %s\n", | ||
515 | GNUNET_i2s (GCP_get_id (route->prev.hop)), | ||
516 | GNUNET_i2s2 (GCP_get_id (route->next.hop)), | ||
517 | GNUNET_sh2s (&route->cid.connection_of_tunnel)); | ||
518 | GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn)); | ||
519 | GNUNET_assert ( | ||
520 | GNUNET_YES == | ||
521 | GNUNET_CONTAINER_multishortmap_remove (routes, | ||
522 | &route->cid.connection_of_tunnel, | ||
523 | route)); | ||
524 | GNUNET_STATISTICS_set (stats, | ||
525 | "# routes", | ||
526 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
527 | GNUNET_NO); | ||
528 | destroy_direction (&route->prev); | ||
529 | destroy_direction (&route->next); | ||
530 | GNUNET_free (route); | ||
531 | } | ||
532 | |||
533 | |||
534 | /** | ||
535 | * Send message that a route is broken between @a peer1 and @a peer2. | ||
536 | * | ||
537 | * @param target where to send the message | ||
538 | * @param cid connection identifier to use | ||
539 | * @param peer1 one of the peers where a link is broken | ||
540 | * @param peer2 another one of the peers where a link is broken | ||
541 | */ | ||
542 | static void | ||
543 | send_broken (struct RouteDirection *target, | ||
544 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
545 | const struct GNUNET_PeerIdentity *peer1, | ||
546 | const struct GNUNET_PeerIdentity *peer2) | ||
547 | { | ||
548 | struct GNUNET_MQ_Envelope *env; | ||
549 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
550 | |||
551 | if (NULL == target->mqm) | ||
552 | return; /* Can't send notification, connection is down! */ | ||
553 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
554 | "Notifying %s about BROKEN route at %s-%s of connection %s\n", | ||
555 | GCP_2s (target->hop), | ||
556 | GNUNET_i2s (peer1), | ||
557 | GNUNET_i2s2 (peer2), | ||
558 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
559 | |||
560 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
561 | bm->cid = *cid; | ||
562 | if (NULL != peer1) | ||
563 | bm->peer1 = *peer1; | ||
564 | if (NULL != peer2) | ||
565 | bm->peer2 = *peer2; | ||
566 | GCP_request_mq_cancel (target->mqm, env); | ||
567 | target->mqm = NULL; | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Function called to check if any routes have timed out, and if | ||
573 | * so, to clean them up. Finally, schedules itself again at the | ||
574 | * earliest time where there might be more work. | ||
575 | * | ||
576 | * @param cls NULL | ||
577 | */ | ||
578 | static void | ||
579 | timeout_cb (void *cls) | ||
580 | { | ||
581 | struct CadetRoute *r; | ||
582 | struct GNUNET_TIME_Relative linger; | ||
583 | struct GNUNET_TIME_Absolute exp; | ||
584 | |||
585 | timeout_task = NULL; | ||
586 | linger = GNUNET_TIME_relative_multiply (keepalive_period, 3); | ||
587 | while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap))) | ||
588 | { | ||
589 | exp = GNUNET_TIME_absolute_add (r->last_use, linger); | ||
590 | if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) | ||
591 | { | ||
592 | /* Route not yet timed out, wait until it does. */ | ||
593 | timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL); | ||
594 | return; | ||
595 | } | ||
596 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
597 | "Sending BROKEN due to timeout (%s was last use, %s linger)\n", | ||
598 | GNUNET_STRINGS_absolute_time_to_string (r->last_use), | ||
599 | GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES)); | ||
600 | send_broken (&r->prev, &r->cid, NULL, NULL); | ||
601 | send_broken (&r->next, &r->cid, NULL, NULL); | ||
602 | destroy_route (r); | ||
603 | } | ||
604 | /* No more routes left, so no need for a #timeout_task */ | ||
605 | } | ||
606 | |||
607 | |||
608 | /** | ||
609 | * Function called when the message queue to the previous hop | ||
610 | * becomes available/unavailable. We expect this function to | ||
611 | * be called immediately when we register, and then again | ||
612 | * later if the connection ever goes down. | ||
613 | * | ||
614 | * @param cls the `struct RouteDirection` | ||
615 | * @param ready #GNUNET_YES if sending is now possible, | ||
616 | * #GNUNET_NO if sending is no longer possible | ||
617 | * #GNUNET_SYSERR if sending is no longer possible | ||
618 | * and the last envelope was discarded | ||
619 | */ | ||
620 | static void | ||
621 | dir_ready_cb (void *cls, int ready) | ||
622 | { | ||
623 | struct RouteDirection *dir = cls; | ||
624 | struct CadetRoute *route = dir->my_route; | ||
625 | struct RouteDirection *odir; | ||
626 | |||
627 | if (GNUNET_YES == ready) | ||
628 | { | ||
629 | struct GNUNET_MQ_Envelope *env; | ||
630 | |||
631 | dir->is_ready = GNUNET_YES; | ||
632 | if (NULL != (env = dir->env_head)) | ||
633 | { | ||
634 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
635 | cur_buffers--; | ||
636 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
637 | lower_rung (dir); | ||
638 | dir->is_ready = GNUNET_NO; | ||
639 | GCP_send (dir->mqm, env); | ||
640 | } | ||
641 | return; | ||
642 | } | ||
643 | odir = (dir == &route->next) ? &route->prev : &route->next; | ||
644 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n"); | ||
645 | send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id); | ||
646 | destroy_route (route); | ||
647 | } | ||
648 | |||
649 | |||
650 | /** | ||
651 | * Initialize one of the directions of a route. | ||
652 | * | ||
653 | * @param route route the direction belongs to | ||
654 | * @param dir direction to initialize | ||
655 | * @param hop next hop on in the @a dir | ||
656 | */ | ||
657 | static void | ||
658 | dir_init (struct RouteDirection *dir, | ||
659 | struct CadetRoute *route, | ||
660 | struct CadetPeer *hop) | ||
661 | { | ||
662 | dir->hop = hop; | ||
663 | dir->my_route = route; | ||
664 | dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir); | ||
665 | GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir); | ||
666 | dir->rung = rung_head; | ||
667 | GNUNET_assert (GNUNET_YES == dir->is_ready); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * We could not create the desired route. Send a | ||
673 | * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
674 | * message to @a target. | ||
675 | * | ||
676 | * @param target who should receive the message | ||
677 | * @param cid identifier of the connection/route that failed | ||
678 | * @param failure_at neighbour with which we failed to route, | ||
679 | * or NULL. | ||
680 | */ | ||
681 | static void | ||
682 | send_broken_without_mqm ( | ||
683 | struct CadetPeer *target, | ||
684 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
685 | const struct GNUNET_PeerIdentity *failure_at) | ||
686 | { | ||
687 | struct GNUNET_MQ_Envelope *env; | ||
688 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
689 | |||
690 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
691 | bm->cid = *cid; | ||
692 | bm->peer1 = my_full_id; | ||
693 | if (NULL != failure_at) | ||
694 | bm->peer2 = *failure_at; | ||
695 | GCP_send_ooo (target, env); | ||
696 | } | ||
697 | |||
698 | |||
699 | /** | ||
700 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | ||
701 | * | ||
702 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
703 | * @param msg Message itself. | ||
704 | */ | ||
705 | static void | ||
706 | handle_connection_create ( | ||
707 | void *cls, | ||
708 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
709 | { | ||
710 | struct CadetPeer *sender = cls; | ||
711 | struct CadetPeer *next; | ||
712 | const struct GNUNET_PeerIdentity *pids = | ||
713 | (const struct GNUNET_PeerIdentity *) &msg[1]; | ||
714 | struct CadetRoute *route; | ||
715 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
716 | unsigned int path_length; | ||
717 | unsigned int off; | ||
718 | struct CadetTunnel *t; | ||
719 | |||
720 | path_length = size / sizeof(struct GNUNET_PeerIdentity); | ||
721 | if (0 == path_length) | ||
722 | { | ||
723 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
724 | "Dropping CADET_CONNECTION_CREATE with empty path\n"); | ||
725 | GNUNET_break_op (0); | ||
726 | return; | ||
727 | } | ||
728 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n", | ||
730 | GCP_2s (sender), | ||
731 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
732 | path_length); | ||
733 | /* Check for loops */ | ||
734 | { | ||
735 | struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
736 | |||
737 | map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES); | ||
738 | GNUNET_assert (NULL != map); | ||
739 | for (unsigned int i = 0; i < path_length; i++) | ||
740 | { | ||
741 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
742 | "CADET_CONNECTION_CREATE has peer %s at offset %u\n", | ||
743 | GNUNET_i2s (&pids[i]), | ||
744 | i); | ||
745 | if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put ( | ||
746 | map, | ||
747 | &pids[i], | ||
748 | NULL, | ||
749 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
750 | { | ||
751 | /* bogus request */ | ||
752 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
753 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
754 | "Dropping CADET_CONNECTION_CREATE with cyclic path\n"); | ||
755 | GNUNET_break_op (0); | ||
756 | return; | ||
757 | } | ||
758 | } | ||
759 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
760 | } | ||
761 | /* Initiator is at offset 0, find us */ | ||
762 | for (off = 1; off < path_length; off++) | ||
763 | if (0 == GNUNET_memcmp (&my_full_id, &pids[off])) | ||
764 | break; | ||
765 | if (off == path_length) | ||
766 | { | ||
767 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
768 | "Dropping CADET_CONNECTION_CREATE without us in the path\n"); | ||
769 | GNUNET_break_op (0); | ||
770 | return; | ||
771 | } | ||
772 | /* Check previous hop */ | ||
773 | if (sender != GCP_get (&pids[off - 1], GNUNET_NO)) | ||
774 | { | ||
775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
776 | "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n"); | ||
777 | GNUNET_break_op (0); | ||
778 | return; | ||
779 | } | ||
780 | if (NULL != (route = get_route (&msg->cid))) | ||
781 | { | ||
782 | /* Duplicate CREATE, pass it on, previous one might have been lost! */ | ||
783 | |||
784 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
785 | "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
786 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
787 | route_message (sender, | ||
788 | &msg->cid, | ||
789 | &msg->header, | ||
790 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | ||
791 | | GNUNET_MQ_PREF_LOW_LATENCY); | ||
792 | return; | ||
793 | } | ||
794 | if (off == path_length - 1) | ||
795 | { | ||
796 | /* We are the destination, create connection */ | ||
797 | struct CadetConnection *cc; | ||
798 | struct CadetPeerPath *path; | ||
799 | struct CadetPeer *origin; | ||
800 | |||
801 | cc = GCC_lookup (&msg->cid); | ||
802 | if (NULL != cc) | ||
803 | { | ||
804 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
805 | "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
806 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
807 | GCC_handle_duplicate_create (cc); | ||
808 | return; | ||
809 | } | ||
810 | |||
811 | origin = GCP_get (&pids[0], GNUNET_YES); | ||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n", | ||
814 | GCP_2s (origin), | ||
815 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
816 | path = GCPP_get_path_from_route (path_length - 1, pids); | ||
817 | t = GCP_get_tunnel (origin, GNUNET_YES); | ||
818 | |||
819 | // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss) | ||
820 | if ((GNUNET_YES == msg->has_monotime) && | ||
821 | (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) && | ||
822 | (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) && | ||
823 | (CADET_TUNNEL_KEY_OK == GCT_get_estate (t))) | ||
824 | { | ||
825 | GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED); | ||
826 | } | ||
827 | |||
828 | if (GNUNET_OK != | ||
829 | GCT_add_inbound_connection (t, | ||
830 | &msg->cid, | ||
831 | path)) | ||
832 | { | ||
833 | /* Send back BROKEN: duplicate connection on the same path, | ||
834 | we will use the other one. */ | ||
835 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
836 | "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n", | ||
837 | GCP_2s (sender), | ||
838 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
839 | GCPP_2s (path)); | ||
840 | send_broken_without_mqm (sender, &msg->cid, NULL); | ||
841 | return; | ||
842 | } | ||
843 | return; | ||
844 | } | ||
845 | /* We are merely a hop on the way, check if we can support the route */ | ||
846 | next = GCP_get (&pids[off + 1], GNUNET_NO); | ||
847 | if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next))) | ||
848 | { | ||
849 | /* unworkable, send back BROKEN notification */ | ||
850 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
851 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", | ||
852 | GCP_2s (sender), | ||
853 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
854 | GNUNET_i2s (&pids[off + 1]), | ||
855 | off + 1); | ||
856 | send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]); | ||
857 | return; | ||
858 | } | ||
859 | if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes)) | ||
860 | { | ||
861 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
862 | "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n", | ||
863 | GCP_2s (sender), | ||
864 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
865 | send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]); | ||
866 | return; | ||
867 | } | ||
868 | |||
869 | /* Workable route, create routing entry */ | ||
870 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
871 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n", | ||
872 | GCP_2s (sender), | ||
873 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
874 | GNUNET_i2s (&pids[off + 1]), | ||
875 | off + 1); | ||
876 | route = GNUNET_new (struct CadetRoute); | ||
877 | route->cid = msg->cid; | ||
878 | route->last_use = GNUNET_TIME_absolute_get (); | ||
879 | dir_init (&route->prev, route, sender); | ||
880 | dir_init (&route->next, route, next); | ||
881 | GNUNET_assert (GNUNET_OK == | ||
882 | GNUNET_CONTAINER_multishortmap_put ( | ||
883 | routes, | ||
884 | &route->cid.connection_of_tunnel, | ||
885 | route, | ||
886 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
887 | GNUNET_STATISTICS_set (stats, | ||
888 | "# routes", | ||
889 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
890 | GNUNET_NO); | ||
891 | route->hn = GNUNET_CONTAINER_heap_insert (route_heap, | ||
892 | route, | ||
893 | route->last_use.abs_value_us); | ||
894 | if (NULL == timeout_task) | ||
895 | timeout_task = | ||
896 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
897 | keepalive_period, | ||
898 | 3), | ||
899 | &timeout_cb, | ||
900 | NULL); | ||
901 | /* also pass CREATE message along to next hop */ | ||
902 | route_message (sender, | ||
903 | &msg->cid, | ||
904 | &msg->header, | ||
905 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
906 | } | ||
907 | |||
908 | |||
909 | /** | ||
910 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK | ||
911 | * | ||
912 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
913 | * @param msg Message itself. | ||
914 | */ | ||
915 | static void | ||
916 | handle_connection_create_ack ( | ||
917 | void *cls, | ||
918 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | ||
919 | { | ||
920 | struct CadetPeer *peer = cls; | ||
921 | struct CadetConnection *cc; | ||
922 | |||
923 | /* First, check if ACK belongs to a connection that ends here. */ | ||
924 | cc = GCC_lookup (&msg->cid); | ||
925 | if (NULL != cc) | ||
926 | { | ||
927 | /* verify ACK came from the right direction */ | ||
928 | unsigned int len; | ||
929 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
930 | |||
931 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
932 | { | ||
933 | /* received ACK from unexpected direction, ignore! */ | ||
934 | GNUNET_break_op (0); | ||
935 | return; | ||
936 | } | ||
937 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
938 | "Received CONNECTION_CREATE_ACK for connection %s.\n", | ||
939 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
940 | GCC_handle_connection_create_ack (cc); | ||
941 | return; | ||
942 | } | ||
943 | |||
944 | /* We're just an intermediary peer, route the message along its path */ | ||
945 | route_message (peer, | ||
946 | &msg->cid, | ||
947 | &msg->header, | ||
948 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
949 | } | ||
950 | |||
951 | |||
952 | /** | ||
953 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
954 | * | ||
955 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
956 | * @param msg Message itself. | ||
957 | * @deprecated duplicate logic with #handle_destroy(); dedup! | ||
958 | */ | ||
959 | static void | ||
960 | handle_connection_broken ( | ||
961 | void *cls, | ||
962 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | ||
963 | { | ||
964 | struct CadetPeer *peer = cls; | ||
965 | struct CadetConnection *cc; | ||
966 | struct CadetRoute *route; | ||
967 | |||
968 | /* First, check if message belongs to a connection that ends here. */ | ||
969 | cc = GCC_lookup (&msg->cid); | ||
970 | if (NULL != cc) | ||
971 | { | ||
972 | /* verify message came from the right direction */ | ||
973 | unsigned int len; | ||
974 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
975 | |||
976 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
977 | { | ||
978 | /* received message from unexpected direction, ignore! */ | ||
979 | GNUNET_break_op (0); | ||
980 | return; | ||
981 | } | ||
982 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
983 | "Received CONNECTION_BROKEN for connection %s. Destroying it.\n", | ||
984 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
985 | GCC_destroy_without_core (cc); | ||
986 | |||
987 | /* FIXME: also destroy the path up to the specified link! */ | ||
988 | return; | ||
989 | } | ||
990 | |||
991 | /* We're just an intermediary peer, route the message along its path */ | ||
992 | route_message (peer, | ||
993 | &msg->cid, | ||
994 | &msg->header, | ||
995 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
996 | route = get_route (&msg->cid); | ||
997 | if (NULL != route) | ||
998 | destroy_route (route); | ||
999 | /* FIXME: also destroy paths we MAY have up to the specified link! */ | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /** | ||
1004 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY | ||
1005 | * | ||
1006 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1007 | * @param msg Message itself. | ||
1008 | */ | ||
1009 | static void | ||
1010 | handle_connection_destroy ( | ||
1011 | void *cls, | ||
1012 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | ||
1013 | { | ||
1014 | struct CadetPeer *peer = cls; | ||
1015 | struct CadetConnection *cc; | ||
1016 | struct CadetRoute *route; | ||
1017 | |||
1018 | /* First, check if message belongs to a connection that ends here. */ | ||
1019 | cc = GCC_lookup (&msg->cid); | ||
1020 | if (NULL != cc) | ||
1021 | { | ||
1022 | /* verify message came from the right direction */ | ||
1023 | unsigned int len; | ||
1024 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1025 | |||
1026 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1027 | { | ||
1028 | /* received message from unexpected direction, ignore! */ | ||
1029 | GNUNET_break_op (0); | ||
1030 | return; | ||
1031 | } | ||
1032 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1033 | "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n", | ||
1034 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1035 | |||
1036 | GCC_destroy_without_core (cc); | ||
1037 | return; | ||
1038 | } | ||
1039 | |||
1040 | /* We're just an intermediary peer, route the message along its path */ | ||
1041 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1042 | "Received CONNECTION_DESTROY for connection %s. Destroying route.\n", | ||
1043 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1044 | route_message (peer, | ||
1045 | &msg->cid, | ||
1046 | &msg->header, | ||
1047 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
1048 | route = get_route (&msg->cid); | ||
1049 | if (NULL != route) | ||
1050 | destroy_route (route); | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /** | ||
1055 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX | ||
1056 | * | ||
1057 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1058 | * @param msg Message itself. | ||
1059 | */ | ||
1060 | static void | ||
1061 | handle_tunnel_kx (void *cls, | ||
1062 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1063 | { | ||
1064 | struct CadetPeer *peer = cls; | ||
1065 | struct CadetConnection *cc; | ||
1066 | |||
1067 | /* First, check if message belongs to a connection that ends here. */ | ||
1068 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1069 | "Routing KX with ephemeral %s on CID %s\n", | ||
1070 | GNUNET_e2s (&msg->ephemeral_key), | ||
1071 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1072 | |||
1073 | |||
1074 | cc = GCC_lookup (&msg->cid); | ||
1075 | if (NULL != cc) | ||
1076 | { | ||
1077 | /* verify message came from the right direction */ | ||
1078 | unsigned int len; | ||
1079 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1080 | |||
1081 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1082 | { | ||
1083 | /* received message from unexpected direction, ignore! */ | ||
1084 | GNUNET_break_op (0); | ||
1085 | return; | ||
1086 | } | ||
1087 | GCC_handle_kx (cc, msg); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | /* We're just an intermediary peer, route the message along its path */ | ||
1092 | route_message (peer, | ||
1093 | &msg->cid, | ||
1094 | &msg->header, | ||
1095 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1096 | } | ||
1097 | |||
1098 | |||
1099 | /** | ||
1100 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH | ||
1101 | * | ||
1102 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1103 | * @param msg Message itself. | ||
1104 | */ | ||
1105 | static void | ||
1106 | handle_tunnel_kx_auth ( | ||
1107 | void *cls, | ||
1108 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1109 | { | ||
1110 | struct CadetPeer *peer = cls; | ||
1111 | struct CadetConnection *cc; | ||
1112 | |||
1113 | /* First, check if message belongs to a connection that ends here. */ | ||
1114 | cc = GCC_lookup (&msg->kx.cid); | ||
1115 | if (NULL != cc) | ||
1116 | { | ||
1117 | /* verify message came from the right direction */ | ||
1118 | unsigned int len; | ||
1119 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1120 | |||
1121 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1122 | { | ||
1123 | /* received message from unexpected direction, ignore! */ | ||
1124 | GNUNET_break_op (0); | ||
1125 | return; | ||
1126 | } | ||
1127 | GCC_handle_kx_auth (cc, msg); | ||
1128 | return; | ||
1129 | } | ||
1130 | |||
1131 | /* We're just an intermediary peer, route the message along its path */ | ||
1132 | route_message (peer, | ||
1133 | &msg->kx.cid, | ||
1134 | &msg->kx.header, | ||
1135 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | /** | ||
1140 | * Check if the encrypted message has the appropriate size. | ||
1141 | * | ||
1142 | * @param cls Closure (unused). | ||
1143 | * @param msg Message to check. | ||
1144 | * | ||
1145 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
1146 | */ | ||
1147 | static int | ||
1148 | check_tunnel_encrypted (void *cls, | ||
1149 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1150 | { | ||
1151 | return GNUNET_YES; | ||
1152 | } | ||
1153 | |||
1154 | |||
1155 | /** | ||
1156 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. | ||
1157 | * | ||
1158 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1159 | * @param msg Message itself. | ||
1160 | */ | ||
1161 | static void | ||
1162 | handle_tunnel_encrypted (void *cls, | ||
1163 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1164 | { | ||
1165 | struct CadetPeer *peer = cls; | ||
1166 | struct CadetConnection *cc; | ||
1167 | |||
1168 | /* First, check if message belongs to a connection that ends here. */ | ||
1169 | cc = GCC_lookup (&msg->cid); | ||
1170 | if (NULL != cc) | ||
1171 | { | ||
1172 | /* verify message came from the right direction */ | ||
1173 | unsigned int len; | ||
1174 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1175 | |||
1176 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1177 | { | ||
1178 | /* received message from unexpected direction, ignore! */ | ||
1179 | GNUNET_break_op (0); | ||
1180 | return; | ||
1181 | } | ||
1182 | GCC_handle_encrypted (cc, msg); | ||
1183 | return; | ||
1184 | } | ||
1185 | /* We're just an intermediary peer, route the message along its path */ | ||
1186 | route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT); | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | /** | ||
1191 | * Function called after #GNUNET_CORE_connect has succeeded (or failed | ||
1192 | * for good). Note that the private key of the peer is intentionally | ||
1193 | * not exposed here; if you need it, your process should try to read | ||
1194 | * the private key file directly (which should work if you are | ||
1195 | * authorized...). Implementations of this function must not call | ||
1196 | * #GNUNET_CORE_disconnect (other than by scheduling a new task to | ||
1197 | * do this later). | ||
1198 | * | ||
1199 | * @param cls closure | ||
1200 | * @param my_identity ID of this peer, NULL if we failed | ||
1201 | */ | ||
1202 | static void | ||
1203 | core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) | ||
1204 | { | ||
1205 | if (NULL == my_identity) | ||
1206 | { | ||
1207 | GNUNET_break (0); | ||
1208 | return; | ||
1209 | } | ||
1210 | GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id)); | ||
1211 | } | ||
1212 | |||
1213 | |||
1214 | /** | ||
1215 | * Method called whenever a given peer connects. | ||
1216 | * | ||
1217 | * @param cls closure | ||
1218 | * @param peer peer identity this notification is about | ||
1219 | */ | ||
1220 | static void * | ||
1221 | core_connect_cb (void *cls, | ||
1222 | const struct GNUNET_PeerIdentity *peer, | ||
1223 | struct GNUNET_MQ_Handle *mq) | ||
1224 | { | ||
1225 | struct CadetPeer *cp; | ||
1226 | |||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1228 | "CORE connection to peer %s was established.\n", | ||
1229 | GNUNET_i2s (peer)); | ||
1230 | cp = GCP_get (peer, GNUNET_YES); | ||
1231 | GCP_set_mq (cp, mq); | ||
1232 | return cp; | ||
1233 | } | ||
1234 | |||
1235 | |||
1236 | /** | ||
1237 | * Method called whenever a peer disconnects. | ||
1238 | * | ||
1239 | * @param cls closure | ||
1240 | * @param peer peer identity this notification is about | ||
1241 | */ | ||
1242 | static void | ||
1243 | core_disconnect_cb (void *cls, | ||
1244 | const struct GNUNET_PeerIdentity *peer, | ||
1245 | void *peer_cls) | ||
1246 | { | ||
1247 | struct CadetPeer *cp = peer_cls; | ||
1248 | |||
1249 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1250 | "CORE connection to peer %s went down.\n", | ||
1251 | GNUNET_i2s (peer)); | ||
1252 | GCP_set_mq (cp, NULL); | ||
1253 | } | ||
1254 | |||
1255 | |||
1256 | /** | ||
1257 | * Initialize the CORE subsystem. | ||
1258 | * | ||
1259 | * @param c Configuration. | ||
1260 | */ | ||
1261 | void | ||
1262 | GCO_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1263 | { | ||
1264 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1265 | { GNUNET_MQ_hd_var_size (connection_create, | ||
1266 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
1267 | struct GNUNET_CADET_ConnectionCreateMessage, | ||
1268 | NULL), | ||
1269 | GNUNET_MQ_hd_fixed_size (connection_create_ack, | ||
1270 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
1271 | struct GNUNET_CADET_ConnectionCreateAckMessage, | ||
1272 | NULL), | ||
1273 | GNUNET_MQ_hd_fixed_size (connection_broken, | ||
1274 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
1275 | struct GNUNET_CADET_ConnectionBrokenMessage, | ||
1276 | NULL), | ||
1277 | GNUNET_MQ_hd_fixed_size (connection_destroy, | ||
1278 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
1279 | struct GNUNET_CADET_ConnectionDestroyMessage, | ||
1280 | NULL), | ||
1281 | GNUNET_MQ_hd_fixed_size (tunnel_kx, | ||
1282 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, | ||
1283 | struct GNUNET_CADET_TunnelKeyExchangeMessage, | ||
1284 | NULL), | ||
1285 | GNUNET_MQ_hd_fixed_size (tunnel_kx_auth, | ||
1286 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH, | ||
1287 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage, | ||
1288 | NULL), | ||
1289 | GNUNET_MQ_hd_var_size (tunnel_encrypted, | ||
1290 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, | ||
1291 | struct GNUNET_CADET_TunnelEncryptedMessage, | ||
1292 | NULL), | ||
1293 | GNUNET_MQ_handler_end () }; | ||
1294 | |||
1295 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1296 | "CADET", | ||
1297 | "MAX_ROUTES", | ||
1298 | &max_routes)) | ||
1299 | max_routes = 5000; | ||
1300 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1301 | "CADET", | ||
1302 | "MAX_MSGS_QUEUE", | ||
1303 | &max_buffers)) | ||
1304 | max_buffers = 10000; | ||
1305 | routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO); | ||
1306 | route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1307 | core = GNUNET_CORE_connect (c, | ||
1308 | NULL, | ||
1309 | &core_init_cb, | ||
1310 | &core_connect_cb, | ||
1311 | &core_disconnect_cb, | ||
1312 | handlers); | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | void | ||
1317 | GCO_shutdown () | ||
1318 | { | ||
1319 | if (NULL != core) | ||
1320 | { | ||
1321 | GNUNET_CORE_disconnect (core); | ||
1322 | core = NULL; | ||
1323 | } | ||
1324 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); | ||
1325 | GNUNET_CONTAINER_multishortmap_destroy (routes); | ||
1326 | routes = NULL; | ||
1327 | GNUNET_CONTAINER_heap_destroy (route_heap); | ||
1328 | route_heap = NULL; | ||
1329 | if (NULL != timeout_task) | ||
1330 | { | ||
1331 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
1332 | timeout_task = NULL; | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | |||
1337 | /* end of gnunet-cadet-service_core.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_core.h b/src/service/cadet/gnunet-service-cadet_core.h new file mode 100644 index 000000000..3438dcb31 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_core.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_core.h | ||
23 | * @brief cadet service; interaction with CORE service | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) | ||
28 | */ | ||
29 | |||
30 | #ifndef GNUNET_SERVICE_CADET_CORE_H | ||
31 | #define GNUNET_SERVICE_CADET_CORE_H | ||
32 | |||
33 | #ifdef __cplusplus | ||
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/service/cadet/gnunet-service-cadet_dht.c b/src/service/cadet/gnunet-service-cadet_dht.c new file mode 100644 index 000000000..dcd1efaa2 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_dht.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_dht.c | ||
22 | * @brief Information we track per peer. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include "gnunet-service-cadet.h" | ||
32 | #include "gnunet-service-cadet_dht.h" | ||
33 | #include "gnunet-service-cadet_hello.h" | ||
34 | #include "gnunet-service-cadet_peer.h" | ||
35 | #include "gnunet-service-cadet_paths.h" | ||
36 | |||
37 | /** | ||
38 | * How long do we wait before first announcing our presence to the DHT. | ||
39 | * Used to wait for our HELLO to be available. Note that we also get | ||
40 | * notifications when our HELLO is ready, so this is just the maximum | ||
41 | * we wait for the first notification. | ||
42 | */ | ||
43 | #define STARTUP_DELAY GNUNET_TIME_relative_multiply ( \ | ||
44 | GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
45 | |||
46 | /** | ||
47 | * How long do we wait after we get an updated HELLO before publishing? | ||
48 | * Allows for the HELLO to be updated again quickly, for example in | ||
49 | * case multiple addresses changed and we got a partial update. | ||
50 | */ | ||
51 | #define CHANGE_DELAY GNUNET_TIME_relative_multiply ( \ | ||
52 | GNUNET_TIME_UNIT_MILLISECONDS, 100) | ||
53 | |||
54 | |||
55 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-dht", __VA_ARGS__) | ||
56 | |||
57 | |||
58 | struct GCD_search_handle | ||
59 | { | ||
60 | /** | ||
61 | * DHT_GET handle. | ||
62 | */ | ||
63 | struct GNUNET_DHT_GetHandle *dhtget; | ||
64 | }; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Handle to use DHT. | ||
69 | */ | ||
70 | static struct GNUNET_DHT_Handle *dht_handle; | ||
71 | |||
72 | /** | ||
73 | * How often to PUT own ID in the DHT. | ||
74 | */ | ||
75 | static struct GNUNET_TIME_Relative id_announce_time; | ||
76 | |||
77 | /** | ||
78 | * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put(). | ||
79 | */ | ||
80 | static unsigned long long dht_replication_level; | ||
81 | |||
82 | /** | ||
83 | * Task to periodically announce itself in the network. | ||
84 | */ | ||
85 | static struct GNUNET_SCHEDULER_Task *announce_id_task; | ||
86 | |||
87 | /** | ||
88 | * Delay for the next ID announce. | ||
89 | */ | ||
90 | static struct GNUNET_TIME_Relative announce_delay; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Function to process paths received for a new peer addition. The recorded | ||
95 | * paths form the initial tunnel, which can be optimized later. | ||
96 | * Called on each result obtained for the DHT search. | ||
97 | * | ||
98 | * @param cls closure | ||
99 | * @param exp when will this value expire | ||
100 | * @param key key of the result | ||
101 | * @param trunc_peer peer preceeding with invalid signature, or NULL | ||
102 | * @param get_path path of the get request | ||
103 | * @param get_path_length length of @a get_path | ||
104 | * @param put_path path of the put request | ||
105 | * @param put_path_length length of the @a put_path | ||
106 | * @param type type of the result | ||
107 | * @param size number of bytes in data | ||
108 | * @param data pointer to the result data | ||
109 | */ | ||
110 | static void | ||
111 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
112 | const struct GNUNET_HashCode *key, | ||
113 | const struct GNUNET_PeerIdentity *trunc_peer, | ||
114 | const struct GNUNET_DHT_PathElement *get_path, | ||
115 | unsigned int get_path_length, | ||
116 | const struct GNUNET_DHT_PathElement *put_path, | ||
117 | unsigned int put_path_length, | ||
118 | enum GNUNET_BLOCK_Type type, | ||
119 | size_t size, | ||
120 | const void *data) | ||
121 | { | ||
122 | const struct GNUNET_MessageHeader *hello = data; | ||
123 | struct GNUNET_HELLO_Builder *builder = GNUNET_HELLO_builder_from_msg (hello); | ||
124 | |||
125 | GNUNET_assert (NULL != builder); | ||
126 | (void) trunc_peer; | ||
127 | GCPP_try_path_from_dht (get_path, | ||
128 | get_path_length, | ||
129 | put_path, | ||
130 | put_path_length); | ||
131 | |||
132 | struct CadetPeer *peer; | ||
133 | |||
134 | peer = GCP_get (&put_path[0].pred, | ||
135 | GNUNET_YES); | ||
136 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
137 | "Got HELLO for %s\n", | ||
138 | GCP_2s (peer)); | ||
139 | GCP_set_hello (peer, | ||
140 | hello); | ||
141 | GNUNET_HELLO_builder_free (builder); | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Periodically announce self id in the DHT | ||
147 | * | ||
148 | * @param cls closure | ||
149 | */ | ||
150 | static void | ||
151 | announce_id (void *cls) | ||
152 | { | ||
153 | struct GNUNET_HashCode phash; | ||
154 | const struct GNUNET_MessageHeader *hello; | ||
155 | size_t size; | ||
156 | size_t block_size; | ||
157 | void *block; | ||
158 | struct GNUNET_TIME_Absolute expiration; | ||
159 | struct GNUNET_TIME_Relative next_put; | ||
160 | |||
161 | hello = GCH_get_mine (); | ||
162 | size = (NULL != hello) ? ntohs(hello->size) : 0; | ||
163 | if (0 == size) | ||
164 | { | ||
165 | expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
166 | announce_delay); | ||
167 | announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | expiration = GNUNET_HELLO_builder_get_expiration_time (hello); | ||
172 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
173 | } | ||
174 | |||
175 | /* Call again in id_announce_time, unless HELLO expires first, | ||
176 | * but wait at least 1s. */ | ||
177 | next_put | ||
178 | = GNUNET_TIME_absolute_get_remaining (expiration); | ||
179 | next_put | ||
180 | = GNUNET_TIME_relative_min (next_put, | ||
181 | id_announce_time); | ||
182 | next_put | ||
183 | = GNUNET_TIME_relative_max (next_put, | ||
184 | GNUNET_TIME_UNIT_SECONDS); | ||
185 | announce_id_task | ||
186 | = GNUNET_SCHEDULER_add_delayed (next_put, | ||
187 | &announce_id, | ||
188 | cls); | ||
189 | GNUNET_STATISTICS_update (stats, | ||
190 | "# DHT announce", | ||
191 | 1, | ||
192 | GNUNET_NO); | ||
193 | memset (&phash, | ||
194 | 0, | ||
195 | sizeof(phash)); | ||
196 | GNUNET_memcpy (&phash, | ||
197 | &my_full_id, | ||
198 | sizeof(my_full_id)); | ||
199 | if (GNUNET_OK != GNUNET_HELLO_dht_msg_to_block (hello, | ||
200 | &my_full_id, | ||
201 | &block, | ||
202 | &block_size, | ||
203 | &expiration)) | ||
204 | return; | ||
205 | |||
206 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
207 | "Announcing my HELLO (%lu bytes) in the DHT\n", | ||
208 | (unsigned long) block_size); | ||
209 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
210 | &phash, /* Key to use */ | ||
211 | dht_replication_level, /* Replication level */ | ||
212 | GNUNET_DHT_RO_RECORD_ROUTE | ||
213 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
214 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
215 | block_size, /* Size of the data */ | ||
216 | (const char *) block, /* Data itself */ | ||
217 | expiration, /* Data expiration */ | ||
218 | NULL, /* Continuation */ | ||
219 | NULL); /* Continuation closure */ | ||
220 | GNUNET_free (block); | ||
221 | } | ||
222 | |||
223 | |||
224 | void | ||
225 | GCD_hello_update () | ||
226 | { | ||
227 | if (NULL == announce_id_task) | ||
228 | return; /* too early */ | ||
229 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
230 | announce_id_task | ||
231 | = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY, | ||
232 | &announce_id, | ||
233 | NULL); | ||
234 | } | ||
235 | |||
236 | |||
237 | void | ||
238 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
239 | { | ||
240 | if (GNUNET_OK != | ||
241 | GNUNET_CONFIGURATION_get_value_number (c, | ||
242 | "CADET", | ||
243 | "DHT_REPLICATION_LEVEL", | ||
244 | &dht_replication_level)) | ||
245 | { | ||
246 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
247 | "CADET", | ||
248 | "DHT_REPLICATION_LEVEL", | ||
249 | "USING DEFAULT"); | ||
250 | dht_replication_level = 3; | ||
251 | } | ||
252 | |||
253 | if (GNUNET_OK != | ||
254 | GNUNET_CONFIGURATION_get_value_time (c, | ||
255 | "CADET", | ||
256 | "ID_ANNOUNCE_TIME", | ||
257 | &id_announce_time)) | ||
258 | { | ||
259 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
260 | "CADET", | ||
261 | "ID_ANNOUNCE_TIME", | ||
262 | "MISSING"); | ||
263 | GNUNET_SCHEDULER_shutdown (); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | dht_handle = GNUNET_DHT_connect (c, | ||
268 | 64); | ||
269 | GNUNET_break (NULL != dht_handle); | ||
270 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
271 | announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY, | ||
272 | &announce_id, | ||
273 | NULL); | ||
274 | } | ||
275 | |||
276 | |||
277 | void | ||
278 | GCD_shutdown (void) | ||
279 | { | ||
280 | if (NULL != dht_handle) | ||
281 | { | ||
282 | GNUNET_DHT_disconnect (dht_handle); | ||
283 | dht_handle = NULL; | ||
284 | } | ||
285 | if (NULL != announce_id_task) | ||
286 | { | ||
287 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
288 | announce_id_task = NULL; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | |||
293 | struct GCD_search_handle * | ||
294 | GCD_search (const struct GNUNET_PeerIdentity *peer_id) | ||
295 | { | ||
296 | struct GNUNET_HashCode phash; | ||
297 | struct GCD_search_handle *h; | ||
298 | |||
299 | GNUNET_STATISTICS_update (stats, | ||
300 | "# DHT search", | ||
301 | 1, | ||
302 | GNUNET_NO); | ||
303 | memset (&phash, | ||
304 | 0, | ||
305 | sizeof(phash)); | ||
306 | GNUNET_memcpy (&phash, | ||
307 | peer_id, | ||
308 | sizeof(*peer_id)); | ||
309 | |||
310 | h = GNUNET_new (struct GCD_search_handle); | ||
311 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
312 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ | ||
313 | &phash, /* key to search */ | ||
314 | dht_replication_level, /* replication level */ | ||
315 | GNUNET_DHT_RO_RECORD_ROUTE | ||
316 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
317 | NULL, /* xquery */ | ||
318 | 0, /* xquery bits */ | ||
319 | &dht_get_id_handler, | ||
320 | h); | ||
321 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
322 | "Starting DHT GET for peer %s (%p)\n", | ||
323 | GNUNET_i2s (peer_id), | ||
324 | h); | ||
325 | return h; | ||
326 | } | ||
327 | |||
328 | |||
329 | void | ||
330 | GCD_search_stop (struct GCD_search_handle *h) | ||
331 | { | ||
332 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
333 | "Stopping DHT GET %p\n", | ||
334 | h); | ||
335 | GNUNET_DHT_get_stop (h->dhtget); | ||
336 | GNUNET_free (h); | ||
337 | } | ||
338 | |||
339 | |||
340 | /* end of gnunet-service-cadet_dht.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_dht.h b/src/service/cadet/gnunet-service-cadet_dht.h new file mode 100644 index 000000000..bcc27f5d2 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_dht.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_dht.h | ||
23 | * @brief cadet service; dealing with DHT requests and results | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCD (Gnunet Cadet Dht) | ||
28 | */ | ||
29 | #ifndef GNUNET_SERVICE_CADET_DHT_H | ||
30 | #define GNUNET_SERVICE_CADET_DHT_H | ||
31 | |||
32 | #ifdef __cplusplus | ||
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/service/cadet/gnunet-service-cadet_hello.c b/src/service/cadet/gnunet-service-cadet_hello.c new file mode 100644 index 000000000..cc28f0fde --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_hello.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2014, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_hello.c | ||
22 | * @brief spread knowledge about how to contact us (get HELLO from peerinfo), | ||
23 | * and remember HELLOs of other peers we have an interest in | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "gnunet_common.h" | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include "gnunet_peerstore_service.h" | ||
32 | #include "cadet_protocol.h" | ||
33 | #include "gnunet-service-cadet.h" | ||
34 | #include "gnunet-service-cadet_dht.h" | ||
35 | #include "gnunet-service-cadet_hello.h" | ||
36 | #include "gnunet-service-cadet_peer.h" | ||
37 | |||
38 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-hll", __VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Hello message of local peer. | ||
42 | */ | ||
43 | static struct GNUNET_MessageHeader *mine; | ||
44 | |||
45 | /** | ||
46 | * Handle to the PEERSTORE service. | ||
47 | */ | ||
48 | static struct GNUNET_PEERSTORE_Handle *peerstore; | ||
49 | |||
50 | /** | ||
51 | * Our peerstore notification context. We use notification | ||
52 | * to instantly learn about new peers as they are discovered. | ||
53 | */ | ||
54 | static struct GNUNET_PEERSTORE_Monitor *peerstore_notify; | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Process each hello message received from peerinfo. | ||
59 | * | ||
60 | * @param cls Closure (unused). | ||
61 | * @param id Identity of the peer. | ||
62 | * @param hello Hello of the peer. | ||
63 | * @param err_msg Error message. | ||
64 | */ | ||
65 | static void | ||
66 | got_hello (void *cls, | ||
67 | const struct GNUNET_PEERSTORE_Record *record, | ||
68 | const char *err_msg) | ||
69 | { | ||
70 | struct CadetPeer *peer; | ||
71 | struct GNUNET_HELLO_Builder *builder; | ||
72 | struct GNUNET_MessageHeader *hello; | ||
73 | |||
74 | if (NULL == record->value) | ||
75 | { | ||
76 | GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1); | ||
77 | return; | ||
78 | } | ||
79 | hello = record->value; | ||
80 | if (0 == GNUNET_memcmp (&record->peer, | ||
81 | &my_full_id)) | ||
82 | { | ||
83 | GNUNET_free (mine); | ||
84 | builder = GNUNET_HELLO_builder_from_msg (hello); | ||
85 | mine = GNUNET_HELLO_builder_to_dht_hello_msg (builder, | ||
86 | my_private_key, | ||
87 | GNUNET_TIME_UNIT_ZERO); | ||
88 | GNUNET_HELLO_builder_free (builder); | ||
89 | GCD_hello_update (); | ||
90 | GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1); | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
95 | "Hello for %s (%d bytes), expires on %s\n", | ||
96 | GNUNET_i2s (&record->peer), | ||
97 | ntohs (hello->size), | ||
98 | GNUNET_STRINGS_absolute_time_to_string ( | ||
99 | GNUNET_HELLO_builder_get_expiration_time (hello))); | ||
100 | peer = GCP_get (&record->peer, | ||
101 | GNUNET_YES); | ||
102 | GCP_set_hello (peer, | ||
103 | hello); | ||
104 | GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1); | ||
105 | } | ||
106 | |||
107 | |||
108 | static void | ||
109 | error_cb (void *cls) | ||
110 | { | ||
111 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
112 | "Error in PEERSTORE monitoring\n"); | ||
113 | } | ||
114 | |||
115 | |||
116 | static void | ||
117 | sync_cb (void *cls) | ||
118 | { | ||
119 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
120 | "Done with initial PEERSTORE iteration during monitoring\n"); | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Initialize the hello subsystem. | ||
126 | * | ||
127 | * @param c Configuration. | ||
128 | */ | ||
129 | void | ||
130 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
131 | { | ||
132 | GNUNET_assert (NULL == peerstore_notify); | ||
133 | peerstore = GNUNET_PEERSTORE_connect (c); | ||
134 | peerstore_notify = | ||
135 | GNUNET_PEERSTORE_monitor_start (c, | ||
136 | GNUNET_YES, | ||
137 | "peerstore", | ||
138 | NULL, | ||
139 | GNUNET_PEERSTORE_HELLO_KEY, | ||
140 | &error_cb, | ||
141 | NULL, | ||
142 | &sync_cb, | ||
143 | NULL, | ||
144 | &got_hello, | ||
145 | NULL); | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Shut down the hello subsystem. | ||
151 | */ | ||
152 | void | ||
153 | GCH_shutdown () | ||
154 | { | ||
155 | if (NULL != peerstore_notify) | ||
156 | { | ||
157 | GNUNET_PEERSTORE_monitor_stop (peerstore_notify); | ||
158 | peerstore_notify = NULL; | ||
159 | } | ||
160 | if (NULL != peerstore) | ||
161 | { | ||
162 | GNUNET_PEERSTORE_disconnect (peerstore); | ||
163 | peerstore = NULL; | ||
164 | } | ||
165 | if (NULL != mine) | ||
166 | { | ||
167 | GNUNET_free (mine); | ||
168 | mine = NULL; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Get own hello message. | ||
175 | * | ||
176 | * @return Own hello message. | ||
177 | */ | ||
178 | const struct GNUNET_MessageHeader * | ||
179 | GCH_get_mine (void) | ||
180 | { | ||
181 | struct GNUNET_HELLO_Builder *builder; | ||
182 | |||
183 | if (NULL == mine) | ||
184 | { | ||
185 | builder = GNUNET_HELLO_builder_new (&my_full_id); | ||
186 | mine = GNUNET_HELLO_builder_to_dht_hello_msg (builder, | ||
187 | my_private_key, | ||
188 | GNUNET_TIME_UNIT_ZERO); | ||
189 | GNUNET_HELLO_builder_free (builder); | ||
190 | } | ||
191 | return mine; | ||
192 | } | ||
193 | |||
194 | |||
195 | /* end of gnunet-service-cadet-new_hello.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_hello.h b/src/service/cadet/gnunet-service-cadet_hello.h new file mode 100644 index 000000000..88c955bb9 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_hello.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2014, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_hello.h | ||
23 | * @brief cadet service; dealing with hello messages | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCH (Gnunet Cadet Hello) | ||
28 | */ | ||
29 | |||
30 | #ifndef GNUNET_SERVICE_CADET_HELLO_H | ||
31 | #define GNUNET_SERVICE_CADET_HELLO_H | ||
32 | |||
33 | #ifdef __cplusplus | ||
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_uri_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_MessageHeader * | ||
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/service/cadet/gnunet-service-cadet_paths.c b/src/service/cadet/gnunet-service-cadet_paths.c new file mode 100644 index 000000000..83b996e05 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_paths.c | |||
@@ -0,0 +1,771 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_paths.c | ||
22 | * @brief Information we track per path. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet-service-cadet_connection.h" | ||
28 | #include "gnunet-service-cadet_tunnels.h" | ||
29 | #include "gnunet-service-cadet_peer.h" | ||
30 | #include "gnunet-service-cadet_paths.h" | ||
31 | |||
32 | |||
33 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-pat", __VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Information regarding a possible path to reach a peer. | ||
38 | */ | ||
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 | struct CadetPeerPath * | ||
598 | GCPP_get_path_from_route (unsigned int path_length, | ||
599 | const struct GNUNET_PeerIdentity *pids) | ||
600 | { | ||
601 | struct CheckMatchContext cm_ctx; | ||
602 | struct CadetPeer *cpath[path_length]; | ||
603 | struct CadetPeerPath *path; | ||
604 | |||
605 | /* precompute inverted 'cpath' so we can avoid doing the lookups and | ||
606 | have the correct order */ | ||
607 | for (unsigned int off = 0; off < path_length; off++) | ||
608 | cpath[off] = GCP_get (&pids[path_length - 1 - off], | ||
609 | GNUNET_YES); | ||
610 | |||
611 | /* First figure out if this path is a subset of an existing path, an | ||
612 | extension of an existing path, or a new path. */ | ||
613 | cm_ctx.cpath = cpath; | ||
614 | cm_ctx.cpath_length = path_length; | ||
615 | cm_ctx.match = NULL; | ||
616 | for (int i = path_length - 1; i >= 0; i--) | ||
617 | { | ||
618 | GCP_iterate_paths_at (cpath[i], | ||
619 | (unsigned int) i, | ||
620 | &check_match, | ||
621 | &cm_ctx); | ||
622 | if (NULL != cm_ctx.match) | ||
623 | { | ||
624 | if (i == path_length - 1) | ||
625 | { | ||
626 | /* Existing path includes this one, return the match! */ | ||
627 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
628 | "Returning existing path %s as inverse for incoming connection\n", | ||
629 | GCPP_2s (cm_ctx.match)); | ||
630 | return cm_ctx.match; | ||
631 | } | ||
632 | if (cm_ctx.match->entries_length == i + 1) | ||
633 | { | ||
634 | /* Existing path ends in the middle of new path, extend it! */ | ||
635 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
636 | "Extending existing path %s to create inverse for incoming connection\n", | ||
637 | GCPP_2s (cm_ctx.match)); | ||
638 | extend_path (cm_ctx.match, | ||
639 | &cpath[i + 1], | ||
640 | path_length - i - 1, | ||
641 | GNUNET_YES); | ||
642 | /* Check that extension was successful */ | ||
643 | GNUNET_assert (cm_ctx.match->entries_length == path_length); | ||
644 | return cm_ctx.match; | ||
645 | } | ||
646 | /* Eh, we found a match but couldn't use it? Something is wrong. */ | ||
647 | GNUNET_break (0); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | /* No match at all, create completely new path */ | ||
652 | path = GNUNET_new (struct CadetPeerPath); | ||
653 | path->entries_length = path_length; | ||
654 | path->entries = GNUNET_new_array (path->entries_length, | ||
655 | struct CadetPeerPathEntry *); | ||
656 | for (int i = path_length - 1; i >= 0; i--) | ||
657 | { | ||
658 | struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry); | ||
659 | |||
660 | path->entries[i] = entry; | ||
661 | entry->peer = cpath[i]; | ||
662 | entry->path = path; | ||
663 | } | ||
664 | for (int i = path_length - 1; i >= 0; i--) | ||
665 | { | ||
666 | struct CadetPeerPathEntry *entry = path->entries[i]; | ||
667 | |||
668 | GCP_path_entry_add (entry->peer, | ||
669 | entry, | ||
670 | i); | ||
671 | } | ||
672 | recalculate_path_desirability (path); | ||
673 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
674 | "Created new path %s to create inverse for incoming connection\n", | ||
675 | GCPP_2s (path)); | ||
676 | path->hn = GCP_attach_path (cpath[path_length - 1], | ||
677 | path, | ||
678 | path_length - 1, | ||
679 | GNUNET_YES); | ||
680 | return path; | ||
681 | } | ||
682 | |||
683 | |||
684 | /** | ||
685 | * Return the length of the path. Excludes one end of the | ||
686 | * path, so the loopback path has length 0. | ||
687 | * | ||
688 | * @param path path to return the length for | ||
689 | * @return number of peers on the path | ||
690 | */ | ||
691 | unsigned int | ||
692 | GCPP_get_length (struct CadetPeerPath *path) | ||
693 | { | ||
694 | return path->entries_length; | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Find peer's offset on path. | ||
700 | * | ||
701 | * @param path path to search | ||
702 | * @param cp peer to look for | ||
703 | * @return offset of @a cp on @a path, or UINT_MAX if not found | ||
704 | */ | ||
705 | unsigned int | ||
706 | GCPP_find_peer (struct CadetPeerPath *path, | ||
707 | struct CadetPeer *cp) | ||
708 | { | ||
709 | for (unsigned int off = 0; | ||
710 | off < path->entries_length; | ||
711 | off++) | ||
712 | if (cp == GCPP_get_peer_at_offset (path, | ||
713 | off)) | ||
714 | return off; | ||
715 | return UINT_MAX; | ||
716 | } | ||
717 | |||
718 | |||
719 | struct CadetPeer * | ||
720 | GCPP_get_peer_at_offset (struct CadetPeerPath *path, | ||
721 | unsigned int off) | ||
722 | { | ||
723 | GNUNET_assert (off < path->entries_length); | ||
724 | return path->entries[off]->peer; | ||
725 | } | ||
726 | |||
727 | |||
728 | /** | ||
729 | * Convert a path to a human-readable string. | ||
730 | * | ||
731 | * @param path path to convert | ||
732 | * @return string, to be freed by caller (unlike other *_2s APIs!) | ||
733 | */ | ||
734 | const char * | ||
735 | GCPP_2s (struct CadetPeerPath *path) | ||
736 | { | ||
737 | static char buf[2048]; | ||
738 | size_t off; | ||
739 | const unsigned int max_plen = (sizeof(buf) - 16) / 5 - 2; /* 5 characters per entry */ | ||
740 | |||
741 | off = 0; | ||
742 | for (unsigned int i = 0; | ||
743 | i < path->entries_length; | ||
744 | i++) | ||
745 | { | ||
746 | if ((path->entries_length > max_plen) && | ||
747 | (i == max_plen / 2)) | ||
748 | off += GNUNET_snprintf (&buf[off], | ||
749 | sizeof(buf) - off, | ||
750 | "...-"); | ||
751 | if ((path->entries_length > max_plen) && | ||
752 | (i > max_plen / 2) && | ||
753 | (i < path->entries_length - max_plen / 2)) | ||
754 | continue; | ||
755 | off += GNUNET_snprintf (&buf[off], | ||
756 | sizeof(buf) - off, | ||
757 | "%s%s", | ||
758 | GNUNET_i2s (GCP_get_id (GCPP_get_peer_at_offset ( | ||
759 | path, | ||
760 | i))), | ||
761 | (i == path->entries_length - 1) ? "" : "-"); | ||
762 | } | ||
763 | GNUNET_snprintf (&buf[off], | ||
764 | sizeof(buf) - off, | ||
765 | "(%p)", | ||
766 | path); | ||
767 | return buf; | ||
768 | } | ||
769 | |||
770 | |||
771 | /* end of gnunet-service-cadet-new_paths.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_paths.h b/src/service/cadet/gnunet-service-cadet_paths.h new file mode 100644 index 000000000..0f3b4dd1a --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_paths.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet-new_paths.h | ||
23 | * @brief Information we track per path. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_PATHS_H | ||
28 | #define GNUNET_SERVICE_CADET_PATHS_H | ||
29 | |||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_dht_service.h" | ||
32 | #include "gnunet-service-cadet.h" | ||
33 | |||
34 | /** | ||
35 | * Create a peer path based on the result of a DHT lookup. If we | ||
36 | * already know this path, or one that is longer, simply return NULL. | ||
37 | * Otherwise, we try to extend an existing path, or create a new one | ||
38 | * if applicable. | ||
39 | * | ||
40 | * @param get_path path of the get request | ||
41 | * @param get_path_length length of @a get_path | ||
42 | * @param put_path path of the put request | ||
43 | * @param put_path_length length of the @a put_path | ||
44 | */ | ||
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 pids path through the network, in reverse order | ||
57 | * (we are at the end, at index @a path_length) | ||
58 | * @return corresponding path object | ||
59 | */ | ||
60 | struct CadetPeerPath * | ||
61 | GCPP_get_path_from_route (unsigned int path_length, | ||
62 | const struct GNUNET_PeerIdentity *pids); | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Return the length of the path. Excludes one end of the | ||
67 | * path, so the loopback path has length 0. | ||
68 | * | ||
69 | * @param path path to return the length for | ||
70 | * @return number of peers on the path | ||
71 | */ | ||
72 | unsigned int | ||
73 | GCPP_get_length (struct CadetPeerPath *path); | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Return connection to @a destination using @a path, or return | ||
78 | * NULL if no such connection exists. | ||
79 | * | ||
80 | * @param path path to traverse | ||
81 | * @param destination destination node to get to, must be on path | ||
82 | * @param off offset of @a destination on @a path | ||
83 | * @return NULL if we have no existing connection | ||
84 | * otherwise connection from us to @a destination via @a path | ||
85 | */ | ||
86 | struct CadetConnection * | ||
87 | GCPP_get_connection (struct CadetPeerPath *path, | ||
88 | struct CadetPeer *destination, | ||
89 | unsigned int off); | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Notify @a path that it is used for connection @a cc | ||
94 | * which ends at the path's offset @a off. | ||
95 | * | ||
96 | * @param path the path to remember the @a cc | ||
97 | * @param off the offset where the @a cc ends | ||
98 | * @param cc the connection to remember | ||
99 | */ | ||
100 | void | ||
101 | GCPP_add_connection (struct CadetPeerPath *path, | ||
102 | unsigned int off, | ||
103 | struct CadetConnection *cc); | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Notify @a path that it is no longer used for connection @a cc which | ||
108 | * ended at the path's offset @a off. | ||
109 | * | ||
110 | * @param path the path to forget the @a cc | ||
111 | * @param off the offset where the @a cc ended | ||
112 | * @param cc the connection to forget | ||
113 | */ | ||
114 | void | ||
115 | GCPP_del_connection (struct CadetPeerPath *path, | ||
116 | unsigned int off, | ||
117 | struct CadetConnection *cc); | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Find peer's offset on path. | ||
122 | * | ||
123 | * @param path path to search | ||
124 | * @param cp peer to look for | ||
125 | * @return offset of @a cp on @a path, or UINT_MAX if not found | ||
126 | */ | ||
127 | unsigned int | ||
128 | GCPP_find_peer (struct CadetPeerPath *path, | ||
129 | struct CadetPeer *cp); | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Return how much we like keeping the path. This is an aggregate | ||
134 | * score based on various factors, including the age of the path | ||
135 | * (older == better), and the value of this path to all of its adjacent | ||
136 | * peers. For example, long paths that end at a peer that we have no | ||
137 | * shorter way to reach are very desirable, while long paths that end | ||
138 | * at a peer for which we have a shorter way as well are much less | ||
139 | * desirable. Higher values indicate more valuable paths. The | ||
140 | * returned value should be used to decide which paths to remember. | ||
141 | * | ||
142 | * @param path path to return the length for | ||
143 | * @return desirability of the path, larger is more desirable | ||
144 | */ | ||
145 | GNUNET_CONTAINER_HeapCostType | ||
146 | GCPP_get_desirability (const struct CadetPeerPath *path); | ||
147 | |||
148 | |||
149 | /** | ||
150 | * The given peer @a cp used to own this @a path. However, it is no | ||
151 | * longer interested in maintaining it, so the path should be | ||
152 | * discarded or shortened (in case a previous peer on the path finds | ||
153 | * the path desirable). | ||
154 | * | ||
155 | * @param path the path that is being released | ||
156 | */ | ||
157 | void | ||
158 | GCPP_release (struct CadetPeerPath *path); | ||
159 | |||
160 | |||
161 | /** | ||
162 | * Obtain the peer at offset @a off in @a path. | ||
163 | * | ||
164 | * @param path peer path to inspect | ||
165 | * @param off offset to return, must be smaller than path length | ||
166 | * @return peer at offset @a off | ||
167 | */ | ||
168 | struct CadetPeer * | ||
169 | GCPP_get_peer_at_offset (struct CadetPeerPath *path, | ||
170 | unsigned int off); | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Convert a path to a human-readable string. | ||
175 | * | ||
176 | * @param path path to convert | ||
177 | * @return string, statically allocated | ||
178 | */ | ||
179 | const char * | ||
180 | GCPP_2s (struct CadetPeerPath *p); | ||
181 | |||
182 | |||
183 | #endif | ||
diff --git a/src/service/cadet/gnunet-service-cadet_peer.c b/src/service/cadet/gnunet-service-cadet_peer.c new file mode 100644 index 000000000..03e8b8962 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_peer.c | |||
@@ -0,0 +1,1554 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.c | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - optimize stopping/restarting DHT search to situations | ||
29 | * where we actually need it (i.e. not if we have a direct connection, | ||
30 | * or if we already have plenty of good short ones, or maybe even | ||
31 | * to take a break if we have some connections and have searched a lot (?)) | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet_time_lib.h" | ||
35 | #include "gnunet_util_lib.h" | ||
36 | #include "gnunet_hello_uri_lib.h" | ||
37 | #include "gnunet_signatures.h" | ||
38 | #include "gnunet_transport_application_service.h" | ||
39 | #include "gnunet_core_service.h" | ||
40 | #include "gnunet_statistics_service.h" | ||
41 | #include "gnunet-service-cadet_peer.h" | ||
42 | #include "gnunet-service-cadet.h" | ||
43 | #include "gnunet-service-cadet_connection.h" | ||
44 | #include "gnunet-service-cadet_dht.h" | ||
45 | #include "gnunet-service-cadet_paths.h" | ||
46 | #include "gnunet-service-cadet_tunnels.h" | ||
47 | |||
48 | |||
49 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__) | ||
50 | |||
51 | |||
52 | /** | ||
53 | * How long do we wait until tearing down an idle peer? | ||
54 | */ | ||
55 | #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
56 | GNUNET_TIME_UNIT_MINUTES, 5) | ||
57 | |||
58 | /** | ||
59 | * How long do we keep paths around if we no longer care about the peer? | ||
60 | */ | ||
61 | #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
62 | GNUNET_TIME_UNIT_MINUTES, 2) | ||
63 | |||
64 | /** | ||
65 | * Queue size when we start dropping OOO messages. | ||
66 | */ | ||
67 | #define MAX_OOO_QUEUE_SIZE 100 | ||
68 | |||
69 | /** | ||
70 | * Data structure used to track whom we have to notify about changes | ||
71 | * to our message queue. | ||
72 | */ | ||
73 | struct GCP_MessageQueueManager | ||
74 | { | ||
75 | /** | ||
76 | * Kept in a DLL. | ||
77 | */ | ||
78 | struct GCP_MessageQueueManager *next; | ||
79 | |||
80 | /** | ||
81 | * Kept in a DLL. | ||
82 | */ | ||
83 | struct GCP_MessageQueueManager *prev; | ||
84 | |||
85 | /** | ||
86 | * Function to call with updated message queue object. | ||
87 | */ | ||
88 | GCP_MessageQueueNotificationCallback cb; | ||
89 | |||
90 | /** | ||
91 | * Closure for @e cb. | ||
92 | */ | ||
93 | void *cb_cls; | ||
94 | |||
95 | /** | ||
96 | * The peer this is for. | ||
97 | */ | ||
98 | struct CadetPeer *cp; | ||
99 | |||
100 | /** | ||
101 | * Envelope this manager would like to transmit once it is its turn. | ||
102 | */ | ||
103 | struct GNUNET_MQ_Envelope *env; | ||
104 | }; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Struct containing all information regarding a given peer | ||
109 | */ | ||
110 | struct CadetPeer | ||
111 | { | ||
112 | /** | ||
113 | * ID of the peer | ||
114 | */ | ||
115 | struct GNUNET_PeerIdentity pid; | ||
116 | |||
117 | /** | ||
118 | * Last time we heard from this peer (currently not used!) | ||
119 | */ | ||
120 | struct GNUNET_TIME_Absolute last_connection_create; | ||
121 | |||
122 | /** | ||
123 | * Array of DLLs of paths traversing the peer, organized by the | ||
124 | * offset of the peer on the larger path. | ||
125 | */ | ||
126 | struct CadetPeerPathEntry **path_heads; | ||
127 | |||
128 | /** | ||
129 | * Array of DLL of paths traversing the peer, organized by the | ||
130 | * offset of the peer on the larger path. | ||
131 | */ | ||
132 | struct CadetPeerPathEntry **path_tails; | ||
133 | |||
134 | /** | ||
135 | * Notifications to call when @e core_mq changes. | ||
136 | */ | ||
137 | struct GCP_MessageQueueManager *mqm_head; | ||
138 | |||
139 | /** | ||
140 | * Notifications to call when @e core_mq changes. | ||
141 | */ | ||
142 | struct GCP_MessageQueueManager *mqm_tail; | ||
143 | |||
144 | /** | ||
145 | * Pointer to first "ready" entry in @e mqm_head. | ||
146 | */ | ||
147 | struct GCP_MessageQueueManager *mqm_ready_ptr; | ||
148 | |||
149 | /** | ||
150 | * MIN-heap of paths owned by this peer (they also end at this | ||
151 | * peer). Ordered by desirability. | ||
152 | */ | ||
153 | struct GNUNET_CONTAINER_Heap *path_heap; | ||
154 | |||
155 | /** | ||
156 | * Handle to stop the DHT search for paths to this peer | ||
157 | */ | ||
158 | struct GCD_search_handle *search_h; | ||
159 | |||
160 | /** | ||
161 | * Task to clean up @e path_heap asynchronously. | ||
162 | */ | ||
163 | struct GNUNET_SCHEDULER_Task *heap_cleanup_task; | ||
164 | |||
165 | /** | ||
166 | * Task to destroy this entry. | ||
167 | */ | ||
168 | struct GNUNET_SCHEDULER_Task *destroy_task; | ||
169 | |||
170 | /** | ||
171 | * Tunnel to this peer, if any. | ||
172 | */ | ||
173 | struct CadetTunnel *t; | ||
174 | |||
175 | /** | ||
176 | * Connections that go through this peer; indexed by tid. | ||
177 | */ | ||
178 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
179 | |||
180 | /** | ||
181 | * Handle for core transmissions. | ||
182 | */ | ||
183 | struct GNUNET_MQ_Handle *core_mq; | ||
184 | |||
185 | /** | ||
186 | * Hello message of the peer. | ||
187 | */ | ||
188 | struct GNUNET_MessageHeader *hello; | ||
189 | |||
190 | /** | ||
191 | * Handle to us offering the HELLO to the transport. | ||
192 | */ | ||
193 | struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer; | ||
194 | |||
195 | /** | ||
196 | * Transport suggest handle. | ||
197 | */ | ||
198 | struct GNUNET_TRANSPORT_ApplicationSuggestHandle *ash; | ||
199 | |||
200 | /** | ||
201 | * How many messages are in the queue to this peer. | ||
202 | */ | ||
203 | unsigned int queue_n; | ||
204 | |||
205 | /** | ||
206 | * How many paths do we have to this peer (in all @e path_heads DLLs combined). | ||
207 | */ | ||
208 | unsigned int num_paths; | ||
209 | |||
210 | /** | ||
211 | * Sum over all of the offsets of all of the paths in the @a path_heads DLLs. | ||
212 | * Used to speed-up #GCP_get_desirability_of_path() calculation. | ||
213 | */ | ||
214 | unsigned int off_sum; | ||
215 | |||
216 | /** | ||
217 | * Number of message queue managers of this peer that have a message in waiting. | ||
218 | * | ||
219 | * Used to quickly see if we need to bother scanning the @e msm_head DLL. | ||
220 | * TODO: could be replaced by another DLL that would then allow us to avoid | ||
221 | * the O(n)-scan of the DLL for ready entries! | ||
222 | */ | ||
223 | unsigned int mqm_ready_counter; | ||
224 | |||
225 | /** | ||
226 | * Current length of the @e path_heads and @e path_tails arrays. | ||
227 | * The arrays should be grown as needed. | ||
228 | */ | ||
229 | unsigned int path_dll_length; | ||
230 | }; | ||
231 | |||
232 | |||
233 | const char * | ||
234 | GCP_2s (const struct CadetPeer *cp) | ||
235 | { | ||
236 | static char buf[5]; | ||
237 | char *ret; | ||
238 | |||
239 | if ((NULL == cp) || | ||
240 | (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key))) | ||
241 | return "NULL"; | ||
242 | |||
243 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key); | ||
244 | if (NULL == ret) | ||
245 | return "NULL"; | ||
246 | |||
247 | GNUNET_strlcpy (buf, | ||
248 | ret, | ||
249 | sizeof(buf)); | ||
250 | GNUNET_free (ret); | ||
251 | return buf; | ||
252 | } | ||
253 | |||
254 | |||
255 | double | ||
256 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
257 | unsigned int off) | ||
258 | { | ||
259 | unsigned int num_alts = cp->num_paths; | ||
260 | unsigned int off_sum; | ||
261 | double avg_sum; | ||
262 | double path_delta; | ||
263 | double weight_alts; | ||
264 | |||
265 | GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */ | ||
266 | GNUNET_assert (0 != cp->path_dll_length); | ||
267 | |||
268 | /* We maintain 'off_sum' in 'peer' and thereby | ||
269 | avoid the SLOW recalculation each time. Kept here | ||
270 | just to document what is going on. */ | ||
271 | #if SLOW | ||
272 | off_sum = 0; | ||
273 | for (unsigned int j = 0; j < cp->path_dll_length; j++) | ||
274 | for (struct CadetPeerPathEntry *pe = cp->path_heads[j]; | ||
275 | NULL != pe; | ||
276 | pe = pe->next) | ||
277 | off_sum += j; | ||
278 | GNUNET_assert (off_sum == cp->off_sum); | ||
279 | #else | ||
280 | off_sum = cp->off_sum; | ||
281 | #endif | ||
282 | avg_sum = off_sum * 1.0 / cp->path_dll_length; | ||
283 | path_delta = off - avg_sum; | ||
284 | /* path_delta positive: path off of peer above average (bad path for peer), | ||
285 | path_delta negative: path off of peer below average (good path for peer) */ | ||
286 | if (path_delta <= -1.0) | ||
287 | weight_alts = -num_alts / path_delta; /* discount alternative paths */ | ||
288 | else if (path_delta >= 1.0) | ||
289 | weight_alts = num_alts * path_delta; /* overcount alternative paths */ | ||
290 | else | ||
291 | weight_alts = num_alts; /* count alternative paths normally */ | ||
292 | |||
293 | |||
294 | /* off+1: long paths are generally harder to find and thus count | ||
295 | a bit more as they get longer. However, above-average paths | ||
296 | still need to count less, hence the squaring of that factor. */ | ||
297 | return (off + 1.0) / (weight_alts * weight_alts); | ||
298 | } | ||
299 | |||
300 | |||
301 | /** | ||
302 | * This peer is no longer be needed, clean it up now. | ||
303 | * | ||
304 | * @param cls peer to clean up | ||
305 | */ | ||
306 | static void | ||
307 | destroy_peer (void *cls) | ||
308 | { | ||
309 | struct CadetPeer *cp = cls; | ||
310 | |||
311 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
312 | "Destroying state about peer %s\n", | ||
313 | GCP_2s (cp)); | ||
314 | cp->destroy_task = NULL; | ||
315 | GNUNET_assert (NULL == cp->t); | ||
316 | GNUNET_assert (NULL == cp->core_mq); | ||
317 | GNUNET_assert (0 == cp->num_paths); | ||
318 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
319 | GNUNET_assert (NULL == cp->path_heads[i]); | ||
320 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); | ||
321 | GNUNET_assert (GNUNET_YES == | ||
322 | GNUNET_CONTAINER_multipeermap_remove (peers, | ||
323 | &cp->pid, | ||
324 | cp)); | ||
325 | GNUNET_free (cp->path_heads); | ||
326 | GNUNET_free (cp->path_tails); | ||
327 | cp->path_dll_length = 0; | ||
328 | if (NULL != cp->search_h) | ||
329 | { | ||
330 | GCD_search_stop (cp->search_h); | ||
331 | cp->search_h = NULL; | ||
332 | } | ||
333 | /* FIXME: clean up search_delayedXXX! */ | ||
334 | |||
335 | |||
336 | if (NULL != cp->ash) | ||
337 | { | ||
338 | GNUNET_TRANSPORT_application_suggest_cancel (cp->ash); | ||
339 | cp->ash = NULL; | ||
340 | } | ||
341 | GNUNET_CONTAINER_multishortmap_destroy (cp->connections); | ||
342 | if (NULL != cp->path_heap) | ||
343 | { | ||
344 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
345 | cp->path_heap = NULL; | ||
346 | } | ||
347 | if (NULL != cp->heap_cleanup_task) | ||
348 | { | ||
349 | GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task); | ||
350 | cp->heap_cleanup_task = NULL; | ||
351 | } | ||
352 | GNUNET_free (cp->hello); | ||
353 | /* Peer should not be freed if paths exist; if there are no paths, | ||
354 | there ought to be no connections, and without connections, no | ||
355 | notifications. Thus we can assert that mqm_head is empty at this | ||
356 | point. */ | ||
357 | GNUNET_assert (NULL == cp->mqm_head); | ||
358 | GNUNET_assert (NULL == cp->mqm_ready_ptr); | ||
359 | GNUNET_free (cp); | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * This peer is now on more "active" duty, activate processes related to it. | ||
365 | * | ||
366 | * @param cp the more-active peer | ||
367 | */ | ||
368 | static void | ||
369 | consider_peer_activate (struct CadetPeer *cp) | ||
370 | { | ||
371 | struct GNUNET_BANDWIDTH_Value32NBO bw; | ||
372 | |||
373 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
374 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
375 | GCP_2s (cp), | ||
376 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
377 | (NULL == cp->t) ? "" : " with tunnel", | ||
378 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
379 | if (NULL != cp->destroy_task) | ||
380 | { | ||
381 | /* It's active, do not destroy! */ | ||
382 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
383 | cp->destroy_task = NULL; | ||
384 | } | ||
385 | if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
386 | (NULL == cp->t)) | ||
387 | { | ||
388 | /* We're just on a path or directly connected; don't bother too much */ | ||
389 | if (NULL != cp->ash) | ||
390 | { | ||
391 | GNUNET_TRANSPORT_application_suggest_cancel (cp->ash); | ||
392 | cp->ash = NULL; | ||
393 | } | ||
394 | if (NULL != cp->search_h) | ||
395 | { | ||
396 | GCD_search_stop (cp->search_h); | ||
397 | cp->search_h = NULL; | ||
398 | } | ||
399 | return; | ||
400 | } | ||
401 | if (NULL == cp->core_mq) | ||
402 | { | ||
403 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
404 | if ((NULL == cp->search_h) && | ||
405 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
406 | cp->search_h | ||
407 | = GCD_search (&cp->pid); | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | /* Have direct connection, stop DHT search if active */ | ||
412 | if (NULL != cp->search_h) | ||
413 | { | ||
414 | GCD_search_stop (cp->search_h); | ||
415 | cp->search_h = NULL; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | if (NULL != cp->ash) | ||
420 | GNUNET_TRANSPORT_application_suggest_cancel (cp->ash); | ||
421 | bw.value__ = 0; | ||
422 | cp->ash | ||
423 | = GNUNET_TRANSPORT_application_suggest (transport, | ||
424 | &cp->pid, | ||
425 | GNUNET_MQ_PRIO_BEST_EFFORT, | ||
426 | bw); | ||
427 | } | ||
428 | |||
429 | |||
430 | /** | ||
431 | * This peer may no longer be needed, consider cleaning it up. | ||
432 | * | ||
433 | * @param cp peer to clean up | ||
434 | */ | ||
435 | static void | ||
436 | consider_peer_destroy (struct CadetPeer *cp); | ||
437 | |||
438 | |||
439 | /** | ||
440 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
441 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
442 | * | ||
443 | * @param cls a `struct CadetPeer`. | ||
444 | */ | ||
445 | static void | ||
446 | drop_paths (void *cls) | ||
447 | { | ||
448 | struct CadetPeer *cp = cls; | ||
449 | struct CadetPeerPath *path; | ||
450 | |||
451 | cp->destroy_task = NULL; | ||
452 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
453 | GCPP_release (path); | ||
454 | consider_peer_destroy (cp); | ||
455 | } | ||
456 | |||
457 | |||
458 | /** | ||
459 | * This peer may no longer be needed, consider cleaning it up. | ||
460 | * | ||
461 | * @param cp peer to clean up | ||
462 | */ | ||
463 | static void | ||
464 | consider_peer_destroy (struct CadetPeer *cp) | ||
465 | { | ||
466 | struct GNUNET_TIME_Relative exp; | ||
467 | |||
468 | if (NULL != cp->destroy_task) | ||
469 | { | ||
470 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
471 | cp->destroy_task = NULL; | ||
472 | } | ||
473 | if (NULL != cp->t) | ||
474 | return; /* still relevant! */ | ||
475 | if (NULL != cp->core_mq) | ||
476 | return; /* still relevant! */ | ||
477 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
478 | return; /* still relevant! */ | ||
479 | if ((NULL != cp->path_heap) && | ||
480 | (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))) | ||
481 | { | ||
482 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
483 | &drop_paths, | ||
484 | cp); | ||
485 | return; | ||
486 | } | ||
487 | if (0 != cp->num_paths) | ||
488 | return; /* still relevant! */ | ||
489 | if (NULL != cp->hello) | ||
490 | { | ||
491 | /* relevant only until HELLO expires */ | ||
492 | exp = GNUNET_TIME_absolute_get_remaining ( | ||
493 | GNUNET_HELLO_builder_get_expiration_time (cp | ||
494 | ->hello)); | ||
495 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
496 | &destroy_peer, | ||
497 | cp); | ||
498 | return; | ||
499 | } | ||
500 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
501 | &destroy_peer, | ||
502 | cp); | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
508 | * | ||
509 | * @param cp peer to modify | ||
510 | * @param mq message queue to set (can be NULL) | ||
511 | */ | ||
512 | void | ||
513 | GCP_set_mq (struct CadetPeer *cp, | ||
514 | struct GNUNET_MQ_Handle *mq) | ||
515 | { | ||
516 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
517 | "Message queue for peer %s is now %p\n", | ||
518 | GCP_2s (cp), | ||
519 | mq); | ||
520 | cp->core_mq = mq; | ||
521 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next; | ||
522 | NULL != mqm; | ||
523 | mqm = next) | ||
524 | { | ||
525 | /* Save next pointer in case mqm gets freed by the callback */ | ||
526 | next = mqm->next; | ||
527 | if (NULL == mq) | ||
528 | { | ||
529 | if (NULL != mqm->env) | ||
530 | { | ||
531 | GNUNET_MQ_discard (mqm->env); | ||
532 | mqm->env = NULL; | ||
533 | mqm->cb (mqm->cb_cls, | ||
534 | GNUNET_SYSERR); | ||
535 | } | ||
536 | else | ||
537 | { | ||
538 | mqm->cb (mqm->cb_cls, | ||
539 | GNUNET_NO); | ||
540 | } | ||
541 | } | ||
542 | else | ||
543 | { | ||
544 | GNUNET_assert (NULL == mqm->env); | ||
545 | mqm->cb (mqm->cb_cls, | ||
546 | GNUNET_YES); | ||
547 | } | ||
548 | } | ||
549 | if ((NULL != mq) || | ||
550 | (NULL != cp->t)) | ||
551 | consider_peer_activate (cp); | ||
552 | else | ||
553 | consider_peer_destroy (cp); | ||
554 | |||
555 | if ((NULL != mq) && | ||
556 | (NULL != cp->t)) | ||
557 | { | ||
558 | /* have a new, direct path to the target, notify tunnel */ | ||
559 | struct CadetPeerPath *path; | ||
560 | |||
561 | path = GCPP_get_path_from_route (1, | ||
562 | &cp->pid); | ||
563 | GCT_consider_path (cp->t, | ||
564 | path, | ||
565 | 0); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * Debug function should NEVER return true in production code, useful to | ||
572 | * simulate losses for testcases. | ||
573 | * | ||
574 | * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. | ||
575 | */ | ||
576 | static int | ||
577 | should_I_drop (void) | ||
578 | { | ||
579 | if (0 == drop_percent) | ||
580 | return GNUNET_NO; | ||
581 | if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
582 | 101) < drop_percent) | ||
583 | return GNUNET_YES; | ||
584 | return GNUNET_NO; | ||
585 | } | ||
586 | |||
587 | |||
588 | /** | ||
589 | * Function called when CORE took one of the messages from | ||
590 | * a message queue manager and transmitted it. | ||
591 | * | ||
592 | * @param cls the `struct CadetPeeer` where we made progress | ||
593 | */ | ||
594 | static void | ||
595 | mqm_send_done (void *cls); | ||
596 | |||
597 | |||
598 | /** | ||
599 | * Transmit current envelope from this @a mqm. | ||
600 | * | ||
601 | * @param mqm mqm to transmit message for now | ||
602 | */ | ||
603 | static void | ||
604 | mqm_execute (struct GCP_MessageQueueManager *mqm) | ||
605 | { | ||
606 | struct CadetPeer *cp = mqm->cp; | ||
607 | |||
608 | /* Move ready pointer to the next entry that might be ready. */ | ||
609 | if ((mqm == cp->mqm_ready_ptr) && | ||
610 | (NULL != mqm->next)) | ||
611 | cp->mqm_ready_ptr = mqm->next; | ||
612 | /* Move entry to the end of the DLL, to be fair. */ | ||
613 | if (mqm != cp->mqm_tail) | ||
614 | { | ||
615 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
616 | cp->mqm_tail, | ||
617 | mqm); | ||
618 | GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head, | ||
619 | cp->mqm_tail, | ||
620 | mqm); | ||
621 | } | ||
622 | cp->mqm_ready_counter--; | ||
623 | if (GNUNET_YES == should_I_drop ()) | ||
624 | { | ||
625 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
626 | "DROPPING message to peer %s from MQM %p\n", | ||
627 | GCP_2s (cp), | ||
628 | mqm); | ||
629 | GNUNET_MQ_discard (mqm->env); | ||
630 | mqm->env = NULL; | ||
631 | mqm_send_done (cp); | ||
632 | } | ||
633 | else | ||
634 | { | ||
635 | { | ||
636 | const struct GNUNET_MessageHeader *mh; | ||
637 | |||
638 | mh = GNUNET_MQ_env_get_msg (mqm->env); | ||
639 | switch (ntohs (mh->type)) | ||
640 | { | ||
641 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
642 | { | ||
643 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg | ||
644 | = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh; | ||
645 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
646 | "P2P forwarding KX with ephemeral %s to %s on CID %s\n", | ||
647 | GNUNET_e2s (&msg->ephemeral_key), | ||
648 | GCP_2s (cp), | ||
649 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
650 | } | ||
651 | break; | ||
652 | |||
653 | default: | ||
654 | break; | ||
655 | } | ||
656 | } | ||
657 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
658 | "Sending to peer %s from MQM %p\n", | ||
659 | GCP_2s (cp), | ||
660 | mqm); | ||
661 | GNUNET_MQ_send (cp->core_mq, | ||
662 | mqm->env); | ||
663 | mqm->env = NULL; | ||
664 | } | ||
665 | mqm->cb (mqm->cb_cls, | ||
666 | GNUNET_YES); | ||
667 | } | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Find the next ready message in the queue (starting | ||
672 | * the search from the `cp->mqm_ready_ptr`) and if possible | ||
673 | * execute the transmission. | ||
674 | * | ||
675 | * @param cp peer to try to send the next ready message to | ||
676 | */ | ||
677 | static void | ||
678 | send_next_ready (struct CadetPeer *cp) | ||
679 | { | ||
680 | struct GCP_MessageQueueManager *mqm; | ||
681 | |||
682 | if (0 == cp->mqm_ready_counter) | ||
683 | return; | ||
684 | while ((NULL != (mqm = cp->mqm_ready_ptr)) && | ||
685 | (NULL == mqm->env)) | ||
686 | cp->mqm_ready_ptr = mqm->next; | ||
687 | if (NULL == mqm) | ||
688 | return; /* nothing to do */ | ||
689 | mqm_execute (mqm); | ||
690 | } | ||
691 | |||
692 | |||
693 | /** | ||
694 | * Function called when CORE took one of the messages from | ||
695 | * a message queue manager and transmitted it. | ||
696 | * | ||
697 | * @param cls the `struct CadetPeeer` where we made progress | ||
698 | */ | ||
699 | static void | ||
700 | mqm_send_done (void *cls) | ||
701 | { | ||
702 | struct CadetPeer *cp = cls; | ||
703 | |||
704 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
705 | "Sending to peer %s completed\n", | ||
706 | GCP_2s (cp)); | ||
707 | send_next_ready (cp); | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
712 | * Send the message in @a env to @a cp. | ||
713 | * | ||
714 | * @param mqm the message queue manager to use for transmission | ||
715 | * @param env envelope with the message to send; must NOT | ||
716 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
717 | */ | ||
718 | void | ||
719 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
720 | struct GNUNET_MQ_Envelope *env) | ||
721 | { | ||
722 | struct CadetPeer *cp = mqm->cp; | ||
723 | |||
724 | GNUNET_assert (NULL != env); | ||
725 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
726 | "Queueing message to peer %s in MQM %p\n", | ||
727 | GCP_2s (cp), | ||
728 | mqm); | ||
729 | GNUNET_assert (NULL != cp->core_mq); | ||
730 | GNUNET_assert (NULL == mqm->env); | ||
731 | GNUNET_MQ_notify_sent (env, | ||
732 | &mqm_send_done, | ||
733 | cp); | ||
734 | mqm->env = env; | ||
735 | cp->mqm_ready_counter++; | ||
736 | if (mqm != cp->mqm_ready_ptr) | ||
737 | cp->mqm_ready_ptr = cp->mqm_head; | ||
738 | if (1 == cp->mqm_ready_counter) | ||
739 | cp->mqm_ready_ptr = mqm; | ||
740 | if (0 != GNUNET_MQ_get_length (cp->core_mq)) | ||
741 | return; | ||
742 | send_next_ready (cp); | ||
743 | } | ||
744 | |||
745 | |||
746 | /** | ||
747 | * Function called to destroy a peer now. | ||
748 | * | ||
749 | * @param cls NULL | ||
750 | * @param pid identity of the peer (unused) | ||
751 | * @param value the `struct CadetPeer` to clean up | ||
752 | * @return #GNUNET_OK (continue to iterate) | ||
753 | */ | ||
754 | static int | ||
755 | destroy_iterator_cb (void *cls, | ||
756 | const struct GNUNET_PeerIdentity *pid, | ||
757 | void *value) | ||
758 | { | ||
759 | struct CadetPeer *cp = value; | ||
760 | |||
761 | if (NULL != cp->destroy_task) | ||
762 | { | ||
763 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
764 | cp->destroy_task = NULL; | ||
765 | } | ||
766 | destroy_peer (cp); | ||
767 | return GNUNET_OK; | ||
768 | } | ||
769 | |||
770 | |||
771 | /** | ||
772 | * Clean up all entries about all peers. | ||
773 | * Must only be called after all tunnels, CORE-connections and | ||
774 | * connections are down. | ||
775 | */ | ||
776 | void | ||
777 | GCP_destroy_all_peers () | ||
778 | { | ||
779 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
780 | "Destroying all peers now\n"); | ||
781 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
782 | &destroy_iterator_cb, | ||
783 | NULL); | ||
784 | } | ||
785 | |||
786 | |||
787 | /** | ||
788 | * Drop all paths owned by this peer, and do not | ||
789 | * allow new ones to be added: We are shutting down. | ||
790 | * | ||
791 | * @param cp peer to drop paths to | ||
792 | */ | ||
793 | void | ||
794 | GCP_drop_owned_paths (struct CadetPeer *cp) | ||
795 | { | ||
796 | struct CadetPeerPath *path; | ||
797 | |||
798 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
799 | "Destroying all paths to %s\n", | ||
800 | GCP_2s (cp)); | ||
801 | while (NULL != (path = | ||
802 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
803 | GCPP_release (path); | ||
804 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
805 | cp->path_heap = NULL; | ||
806 | } | ||
807 | |||
808 | |||
809 | /** | ||
810 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
811 | * | ||
812 | * @param cp peer to modify | ||
813 | * @param entry an entry on a path | ||
814 | * @param off offset of this peer on the path | ||
815 | */ | ||
816 | void | ||
817 | GCP_path_entry_add (struct CadetPeer *cp, | ||
818 | struct CadetPeerPathEntry *entry, | ||
819 | unsigned int off) | ||
820 | { | ||
821 | GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path, | ||
822 | off)); | ||
823 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
824 | "Discovered that peer %s is on path %s at offset %u\n", | ||
825 | GCP_2s (cp), | ||
826 | GCPP_2s (entry->path), | ||
827 | off); | ||
828 | if (off >= cp->path_dll_length) | ||
829 | { | ||
830 | unsigned int len = cp->path_dll_length; | ||
831 | |||
832 | GNUNET_array_grow (cp->path_heads, | ||
833 | len, | ||
834 | off + 4); | ||
835 | GNUNET_array_grow (cp->path_tails, | ||
836 | cp->path_dll_length, | ||
837 | off + 4); | ||
838 | } | ||
839 | GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], | ||
840 | cp->path_tails[off], | ||
841 | entry); | ||
842 | cp->off_sum += off; | ||
843 | cp->num_paths++; | ||
844 | |||
845 | /* If we have a tunnel to this peer, tell the tunnel that there is a | ||
846 | new path available. */ | ||
847 | if (NULL != cp->t) | ||
848 | GCT_consider_path (cp->t, | ||
849 | entry->path, | ||
850 | off); | ||
851 | |||
852 | if ((NULL != cp->search_h) && | ||
853 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths)) | ||
854 | { | ||
855 | /* Now I have enough paths, stop search */ | ||
856 | GCD_search_stop (cp->search_h); | ||
857 | cp->search_h = NULL; | ||
858 | } | ||
859 | if (NULL != cp->destroy_task) | ||
860 | { | ||
861 | /* paths changed, this resets the destroy timeout counter | ||
862 | and aborts a destroy task that may no longer be valid | ||
863 | to have (as we now have more paths via this peer). */ | ||
864 | consider_peer_destroy (cp); | ||
865 | } | ||
866 | } | ||
867 | |||
868 | |||
869 | /** | ||
870 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
871 | * | ||
872 | * @param cp peer to modify | ||
873 | * @param entry an entry on a path | ||
874 | * @param off offset of this peer on the path | ||
875 | */ | ||
876 | void | ||
877 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
878 | struct CadetPeerPathEntry *entry, | ||
879 | unsigned int off) | ||
880 | { | ||
881 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
882 | "Removing knowledge about peer %s beging on path %s at offset %u\n", | ||
883 | GCP_2s (cp), | ||
884 | GCPP_2s (entry->path), | ||
885 | off); | ||
886 | GNUNET_CONTAINER_DLL_remove (cp->path_heads[off], | ||
887 | cp->path_tails[off], | ||
888 | entry); | ||
889 | GNUNET_assert (0 < cp->num_paths); | ||
890 | cp->off_sum -= off; | ||
891 | cp->num_paths--; | ||
892 | if ((NULL == cp->core_mq) && | ||
893 | (NULL != cp->t) && | ||
894 | (NULL == cp->search_h) && | ||
895 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
896 | cp->search_h | ||
897 | = GCD_search (&cp->pid); | ||
898 | if (NULL == cp->destroy_task) | ||
899 | { | ||
900 | /* paths changed, we might now be ready for destruction, check again */ | ||
901 | consider_peer_destroy (cp); | ||
902 | } | ||
903 | } | ||
904 | |||
905 | |||
906 | /** | ||
907 | * Prune down the number of paths to this peer, we seem to | ||
908 | * have way too many. | ||
909 | * | ||
910 | * @param cls the `struct CadetPeer` to maintain the path heap for | ||
911 | */ | ||
912 | static void | ||
913 | path_heap_cleanup (void *cls) | ||
914 | { | ||
915 | struct CadetPeer *cp = cls; | ||
916 | struct CadetPeerPath *root; | ||
917 | |||
918 | cp->heap_cleanup_task = NULL; | ||
919 | while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
920 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
921 | { | ||
922 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
923 | (Note that this intentionally keeps highly desirable, but currently | ||
924 | unused paths around in the hope that we might be able to switch, even | ||
925 | if the number of paths exceeds the threshold.) */ | ||
926 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
927 | GNUNET_assert (NULL != root); | ||
928 | if (NULL != | ||
929 | GCPP_get_connection (root, | ||
930 | cp, | ||
931 | GCPP_get_length (root) - 1)) | ||
932 | break; /* can't fix */ | ||
933 | /* Got plenty of paths to this destination, and this is a low-quality | ||
934 | one that we don't care about. Allow it to die. */ | ||
935 | GNUNET_assert (root == | ||
936 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
937 | GCPP_release (root); | ||
938 | } | ||
939 | } | ||
940 | |||
941 | |||
942 | struct GNUNET_CONTAINER_HeapNode * | ||
943 | GCP_attach_path (struct CadetPeer *cp, | ||
944 | struct CadetPeerPath *path, | ||
945 | unsigned int off, | ||
946 | int force) | ||
947 | { | ||
948 | GNUNET_CONTAINER_HeapCostType desirability; | ||
949 | struct CadetPeerPath *root; | ||
950 | GNUNET_CONTAINER_HeapCostType root_desirability; | ||
951 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
952 | |||
953 | GNUNET_assert (off == GCPP_get_length (path) - 1); | ||
954 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, | ||
955 | off)); | ||
956 | if (NULL == cp->path_heap) | ||
957 | { | ||
958 | /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ | ||
959 | GNUNET_assert (GNUNET_NO == force); | ||
960 | return NULL; | ||
961 | } | ||
962 | desirability = GCPP_get_desirability (path); | ||
963 | if (GNUNET_NO == force) | ||
964 | { | ||
965 | /* FIXME: desirability is not yet initialized; tricky! */ | ||
966 | if (GNUNET_NO == | ||
967 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | ||
968 | (void **) &root, | ||
969 | &root_desirability)) | ||
970 | { | ||
971 | root = NULL; | ||
972 | root_desirability = 0; | ||
973 | } | ||
974 | |||
975 | if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && | ||
976 | (desirability < root_desirability)) | ||
977 | { | ||
978 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
979 | "Decided to not attach path %s to peer %s due to undesirability\n", | ||
980 | GCPP_2s (path), | ||
981 | GCP_2s (cp)); | ||
982 | return NULL; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
987 | "Attaching path %s to peer %s (%s)\n", | ||
988 | GCPP_2s (path), | ||
989 | GCP_2s (cp), | ||
990 | (GNUNET_NO == force) ? "desirable" : "forced"); | ||
991 | |||
992 | /* Yes, we'd like to add this path, add to our heap */ | ||
993 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | ||
994 | path, | ||
995 | desirability); | ||
996 | |||
997 | /* Consider maybe dropping other paths because of the new one */ | ||
998 | if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
999 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
1000 | (NULL != cp->heap_cleanup_task)) | ||
1001 | cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup, | ||
1002 | cp); | ||
1003 | return hn; | ||
1004 | } | ||
1005 | |||
1006 | |||
1007 | /** | ||
1008 | * This peer can no longer own @a path as the path | ||
1009 | * has been extended and a peer further down the line | ||
1010 | * is now the new owner. | ||
1011 | * | ||
1012 | * @param cp old owner of the @a path | ||
1013 | * @param path path where the ownership is lost | ||
1014 | * @param hn note in @a cp's path heap that must be deleted | ||
1015 | */ | ||
1016 | void | ||
1017 | GCP_detach_path (struct CadetPeer *cp, | ||
1018 | struct CadetPeerPath *path, | ||
1019 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
1020 | { | ||
1021 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1022 | "Detaching path %s from peer %s\n", | ||
1023 | GCPP_2s (path), | ||
1024 | GCP_2s (cp)); | ||
1025 | GNUNET_assert (path == | ||
1026 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
1027 | } | ||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * Add a @a connection to this @a cp. | ||
1032 | * | ||
1033 | * @param cp peer via which the @a connection goes | ||
1034 | * @param cc the connection to add | ||
1035 | */ | ||
1036 | void | ||
1037 | GCP_add_connection (struct CadetPeer *cp, | ||
1038 | struct CadetConnection *cc) | ||
1039 | { | ||
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1041 | "Adding %s to peer %s\n", | ||
1042 | GCC_2s (cc), | ||
1043 | GCP_2s (cp)); | ||
1044 | GNUNET_assert (GNUNET_OK == | ||
1045 | GNUNET_CONTAINER_multishortmap_put (cp->connections, | ||
1046 | &GCC_get_id ( | ||
1047 | cc)->connection_of_tunnel, | ||
1048 | cc, | ||
1049 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1050 | if (NULL != cp->destroy_task) | ||
1051 | { | ||
1052 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
1053 | cp->destroy_task = NULL; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | |||
1058 | /** | ||
1059 | * Remove a @a connection that went via this @a cp. | ||
1060 | * | ||
1061 | * @param cp peer via which the @a connection went | ||
1062 | * @param cc the connection to remove | ||
1063 | */ | ||
1064 | void | ||
1065 | GCP_remove_connection (struct CadetPeer *cp, | ||
1066 | struct CadetConnection *cc) | ||
1067 | { | ||
1068 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1069 | "Removing connection %s from peer %s\n", | ||
1070 | GCC_2s (cc), | ||
1071 | GCP_2s (cp)); | ||
1072 | GNUNET_assert (GNUNET_YES == | ||
1073 | GNUNET_CONTAINER_multishortmap_remove (cp->connections, | ||
1074 | &GCC_get_id ( | ||
1075 | cc)-> | ||
1076 | connection_of_tunnel, | ||
1077 | cc)); | ||
1078 | consider_peer_destroy (cp); | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
1083 | * Retrieve the CadetPeer structure associated with the | ||
1084 | * peer. Optionally create one and insert it in the appropriate | ||
1085 | * structures if the peer is not known yet. | ||
1086 | * | ||
1087 | * @param peer_id Full identity of the peer. | ||
1088 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
1089 | * #GNUNET_NO to return NULL if peer is unknown. | ||
1090 | * @return Existing or newly created peer structure. | ||
1091 | * NULL if unknown and not requested @a create | ||
1092 | */ | ||
1093 | struct CadetPeer * | ||
1094 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
1095 | int create) | ||
1096 | { | ||
1097 | struct CadetPeer *cp; | ||
1098 | |||
1099 | cp = GNUNET_CONTAINER_multipeermap_get (peers, | ||
1100 | peer_id); | ||
1101 | if (NULL != cp) | ||
1102 | return cp; | ||
1103 | if (GNUNET_NO == create) | ||
1104 | return NULL; | ||
1105 | cp = GNUNET_new (struct CadetPeer); | ||
1106 | cp->pid = *peer_id; | ||
1107 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | ||
1108 | GNUNET_YES); | ||
1109 | cp->path_heap = GNUNET_CONTAINER_heap_create ( | ||
1110 | GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1111 | GNUNET_assert (GNUNET_YES == | ||
1112 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
1113 | &cp->pid, | ||
1114 | cp, | ||
1115 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1116 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1117 | "Creating peer %s\n", | ||
1118 | GCP_2s (cp)); | ||
1119 | return cp; | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /** | ||
1124 | * Obtain the peer identity for a `struct CadetPeer`. | ||
1125 | * | ||
1126 | * @param cp our peer handle | ||
1127 | * @return the peer identity | ||
1128 | */ | ||
1129 | const struct GNUNET_PeerIdentity * | ||
1130 | GCP_get_id (struct CadetPeer *cp) | ||
1131 | { | ||
1132 | return &cp->pid; | ||
1133 | } | ||
1134 | |||
1135 | |||
1136 | /** | ||
1137 | * Iterate over all known peers. | ||
1138 | * | ||
1139 | * @param iter Iterator. | ||
1140 | * @param cls Closure for @c iter. | ||
1141 | */ | ||
1142 | void | ||
1143 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
1144 | void *cls) | ||
1145 | { | ||
1146 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
1147 | iter, | ||
1148 | cls); | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | /** | ||
1153 | * Count the number of known paths toward the peer. | ||
1154 | * | ||
1155 | * @param cp Peer to get path info. | ||
1156 | * @return Number of known paths. | ||
1157 | */ | ||
1158 | unsigned int | ||
1159 | GCP_count_paths (const struct CadetPeer *cp) | ||
1160 | { | ||
1161 | return cp->num_paths; | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | /** | ||
1166 | * Iterate over the paths to a peer. | ||
1167 | * | ||
1168 | * @param cp Peer to get path info. | ||
1169 | * @param callback Function to call for every path. | ||
1170 | * @param callback_cls Closure for @a callback. | ||
1171 | * @return Number of iterated paths. | ||
1172 | */ | ||
1173 | unsigned int | ||
1174 | GCP_iterate_paths (struct CadetPeer *cp, | ||
1175 | GCP_PathIterator callback, | ||
1176 | void *callback_cls) | ||
1177 | { | ||
1178 | unsigned int ret = 0; | ||
1179 | |||
1180 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1181 | "Iterating over paths to peer %s%s\n", | ||
1182 | GCP_2s (cp), | ||
1183 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
1184 | if (NULL != cp->core_mq) | ||
1185 | { | ||
1186 | /* FIXME: this branch seems to duplicate the | ||
1187 | i=0 case below (direct link). Leave out!??? -CG */ | ||
1188 | struct CadetPeerPath *path; | ||
1189 | |||
1190 | path = GCPP_get_path_from_route (1, | ||
1191 | &cp->pid); | ||
1192 | ret++; | ||
1193 | if (GNUNET_NO == | ||
1194 | callback (callback_cls, | ||
1195 | path, | ||
1196 | 0)) | ||
1197 | return ret; | ||
1198 | } | ||
1199 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
1200 | { | ||
1201 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1202 | NULL != pe; | ||
1203 | pe = pe->next) | ||
1204 | { | ||
1205 | ret++; | ||
1206 | if (GNUNET_NO == | ||
1207 | callback (callback_cls, | ||
1208 | pe->path, | ||
1209 | i)) | ||
1210 | return ret; | ||
1211 | } | ||
1212 | } | ||
1213 | return ret; | ||
1214 | } | ||
1215 | |||
1216 | |||
1217 | /** | ||
1218 | * Iterate over the paths to a peer without direct link. | ||
1219 | * | ||
1220 | * @param cp Peer to get path info. | ||
1221 | * @param callback Function to call for every path. | ||
1222 | * @param callback_cls Closure for @a callback. | ||
1223 | * @return Number of iterated paths. | ||
1224 | */ | ||
1225 | unsigned int | ||
1226 | GCP_iterate_indirect_paths (struct CadetPeer *cp, | ||
1227 | GCP_PathIterator callback, | ||
1228 | void *callback_cls) | ||
1229 | { | ||
1230 | unsigned int ret = 0; | ||
1231 | |||
1232 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1233 | "Iterating over paths to peer %s without direct link\n", | ||
1234 | GCP_2s (cp)); | ||
1235 | for (unsigned int i = 1; i < cp->path_dll_length; i++) | ||
1236 | { | ||
1237 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1238 | NULL != pe; | ||
1239 | pe = pe->next) | ||
1240 | { | ||
1241 | ret++; | ||
1242 | if (GNUNET_NO == | ||
1243 | callback (callback_cls, | ||
1244 | pe->path, | ||
1245 | i)) | ||
1246 | return ret; | ||
1247 | } | ||
1248 | } | ||
1249 | return ret; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | unsigned int | ||
1254 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
1255 | unsigned int dist, | ||
1256 | GCP_PathIterator callback, | ||
1257 | void *callback_cls) | ||
1258 | { | ||
1259 | unsigned int ret = 0; | ||
1260 | |||
1261 | if (dist >= cp->path_dll_length) | ||
1262 | { | ||
1263 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1264 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", | ||
1265 | dist, | ||
1266 | cp->path_dll_length); | ||
1267 | return 0; | ||
1268 | } | ||
1269 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; | ||
1270 | NULL != pe; | ||
1271 | pe = pe->next) | ||
1272 | { | ||
1273 | if (GNUNET_NO == | ||
1274 | callback (callback_cls, | ||
1275 | pe->path, | ||
1276 | dist)) | ||
1277 | return ret; | ||
1278 | ret++; | ||
1279 | } | ||
1280 | return ret; | ||
1281 | } | ||
1282 | |||
1283 | |||
1284 | /** | ||
1285 | * Get the tunnel towards a peer. | ||
1286 | * | ||
1287 | * @param cp Peer to get from. | ||
1288 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
1289 | * @return Tunnel towards peer. | ||
1290 | */ | ||
1291 | struct CadetTunnel * | ||
1292 | GCP_get_tunnel (struct CadetPeer *cp, | ||
1293 | int create) | ||
1294 | { | ||
1295 | if (NULL == cp) | ||
1296 | return NULL; | ||
1297 | if ((NULL != cp->t) || | ||
1298 | (GNUNET_NO == create)) | ||
1299 | return cp->t; | ||
1300 | cp->t = GCT_create_tunnel (cp); | ||
1301 | consider_peer_activate (cp); | ||
1302 | return cp->t; | ||
1303 | } | ||
1304 | |||
1305 | |||
1306 | void | ||
1307 | GCP_set_hello (struct CadetPeer *cp, | ||
1308 | const struct GNUNET_MessageHeader *hello) | ||
1309 | { | ||
1310 | struct GNUNET_BANDWIDTH_Value32NBO bw; | ||
1311 | uint16_t size = ntohs (hello->size); | ||
1312 | |||
1313 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1314 | "Got %u byte HELLO for peer %s\n", | ||
1315 | (unsigned int) size, | ||
1316 | GCP_2s (cp)); | ||
1317 | if (NULL != cp->hello) | ||
1318 | { | ||
1319 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
1320 | |||
1321 | struct GNUNET_TIME_Absolute new_hello_exp = | ||
1322 | GNUNET_HELLO_builder_get_expiration_time (hello); | ||
1323 | struct GNUNET_TIME_Absolute old_hello_exp = | ||
1324 | GNUNET_HELLO_builder_get_expiration_time (cp | ||
1325 | ->hello); | ||
1326 | |||
1327 | if (GNUNET_TIME_absolute_cmp (new_hello_exp, >, now) && | ||
1328 | GNUNET_TIME_absolute_cmp (new_hello_exp, >, old_hello_exp)) | ||
1329 | { | ||
1330 | GNUNET_free (cp->hello); | ||
1331 | cp->hello = GNUNET_malloc (size); | ||
1332 | GNUNET_memcpy (cp->hello, hello, size); | ||
1333 | } | ||
1334 | else | ||
1335 | { | ||
1336 | return; | ||
1337 | } | ||
1338 | } | ||
1339 | else | ||
1340 | { | ||
1341 | cp->hello = GNUNET_memdup (hello, | ||
1342 | size); | ||
1343 | } | ||
1344 | if (NULL != cp->ash) | ||
1345 | GNUNET_TRANSPORT_application_suggest_cancel (cp->ash); | ||
1346 | bw.value__ = 0; | ||
1347 | cp->ash | ||
1348 | = GNUNET_TRANSPORT_application_suggest (transport, | ||
1349 | &cp->pid, | ||
1350 | GNUNET_MQ_PRIO_BEST_EFFORT, | ||
1351 | bw); | ||
1352 | /* New HELLO means cp's destruction time may change... */ | ||
1353 | consider_peer_destroy (cp); | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | /** | ||
1358 | * The tunnel to the given peer no longer exists, remove it from our | ||
1359 | * data structures, and possibly clean up the peer itself. | ||
1360 | * | ||
1361 | * @param cp the peer affected | ||
1362 | * @param t the dead tunnel | ||
1363 | */ | ||
1364 | void | ||
1365 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
1366 | struct CadetTunnel *t) | ||
1367 | { | ||
1368 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1369 | "Dropping tunnel %s to peer %s\n", | ||
1370 | GCT_2s (t), | ||
1371 | GCP_2s (cp)); | ||
1372 | GNUNET_assert (cp->t == t); | ||
1373 | cp->t = NULL; | ||
1374 | consider_peer_destroy (cp); | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | /** | ||
1379 | * Test if @a cp has a core-level connection | ||
1380 | * | ||
1381 | * @param cp peer to test | ||
1382 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
1383 | */ | ||
1384 | int | ||
1385 | GCP_has_core_connection (struct CadetPeer *cp) | ||
1386 | { | ||
1387 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; | ||
1388 | } | ||
1389 | |||
1390 | |||
1391 | /** | ||
1392 | * Start message queue change notifications. | ||
1393 | * | ||
1394 | * @param cp peer to notify for | ||
1395 | * @param cb function to call if mq becomes available or unavailable | ||
1396 | * @param cb_cls closure for @a cb | ||
1397 | * @return handle to cancel request | ||
1398 | */ | ||
1399 | struct GCP_MessageQueueManager * | ||
1400 | GCP_request_mq (struct CadetPeer *cp, | ||
1401 | GCP_MessageQueueNotificationCallback cb, | ||
1402 | void *cb_cls) | ||
1403 | { | ||
1404 | struct GCP_MessageQueueManager *mqm; | ||
1405 | |||
1406 | mqm = GNUNET_new (struct GCP_MessageQueueManager); | ||
1407 | mqm->cb = cb; | ||
1408 | mqm->cb_cls = cb_cls; | ||
1409 | mqm->cp = cp; | ||
1410 | GNUNET_CONTAINER_DLL_insert (cp->mqm_head, | ||
1411 | cp->mqm_tail, | ||
1412 | mqm); | ||
1413 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1414 | "Creating MQM %p for peer %s\n", | ||
1415 | mqm, | ||
1416 | GCP_2s (cp)); | ||
1417 | if (NULL != cp->core_mq) | ||
1418 | cb (cb_cls, | ||
1419 | GNUNET_YES); | ||
1420 | return mqm; | ||
1421 | } | ||
1422 | |||
1423 | |||
1424 | /** | ||
1425 | * Stops message queue change notifications. | ||
1426 | * | ||
1427 | * @param mqm handle matching request to cancel | ||
1428 | * @param last_env final message to transmit, or NULL | ||
1429 | */ | ||
1430 | void | ||
1431 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
1432 | struct GNUNET_MQ_Envelope *last_env) | ||
1433 | { | ||
1434 | struct CadetPeer *cp = mqm->cp; | ||
1435 | |||
1436 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1437 | "Destroying MQM %p for peer %s%s\n", | ||
1438 | mqm, | ||
1439 | GCP_2s (cp), | ||
1440 | (NULL == last_env) ? "" : " with last ditch transmission"); | ||
1441 | if (NULL != mqm->env) | ||
1442 | GNUNET_MQ_discard (mqm->env); | ||
1443 | if (NULL != last_env) | ||
1444 | { | ||
1445 | if (NULL != cp->core_mq) | ||
1446 | { | ||
1447 | GNUNET_MQ_notify_sent (last_env, | ||
1448 | &mqm_send_done, | ||
1449 | cp); | ||
1450 | GNUNET_MQ_send (cp->core_mq, | ||
1451 | last_env); | ||
1452 | } | ||
1453 | else | ||
1454 | { | ||
1455 | GNUNET_MQ_discard (last_env); | ||
1456 | } | ||
1457 | } | ||
1458 | if (cp->mqm_ready_ptr == mqm) | ||
1459 | cp->mqm_ready_ptr = mqm->next; | ||
1460 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
1461 | cp->mqm_tail, | ||
1462 | mqm); | ||
1463 | GNUNET_free (mqm); | ||
1464 | } | ||
1465 | |||
1466 | |||
1467 | /** | ||
1468 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
1469 | * This function should only be used to send error messages outside | ||
1470 | * of flow and congestion control, similar to ICMP. Note that | ||
1471 | * the envelope may be silently discarded as well. | ||
1472 | * | ||
1473 | * @param cp peer to send the message to | ||
1474 | * @param env envelope with the message to send | ||
1475 | */ | ||
1476 | void | ||
1477 | GCP_send_ooo (struct CadetPeer *cp, | ||
1478 | struct GNUNET_MQ_Envelope *env) | ||
1479 | { | ||
1480 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1481 | "Sending message to %s out of management\n", | ||
1482 | GCP_2s (cp)); | ||
1483 | if (NULL == cp->core_mq) | ||
1484 | { | ||
1485 | GNUNET_MQ_discard (env); | ||
1486 | return; | ||
1487 | } | ||
1488 | if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE) | ||
1489 | { | ||
1490 | GNUNET_MQ_discard (env); | ||
1491 | return; | ||
1492 | } | ||
1493 | GNUNET_MQ_notify_sent (env, | ||
1494 | &mqm_send_done, | ||
1495 | cp); | ||
1496 | GNUNET_MQ_send (cp->core_mq, | ||
1497 | env); | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | /** | ||
1502 | * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer. | ||
1503 | * | ||
1504 | * @param peer The peer we received a new time value from. | ||
1505 | * @param monotime Time value we check against the last time value we received from a peer. | ||
1506 | * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer. | ||
1507 | */ | ||
1508 | int | ||
1509 | GCP_check_and_update_monotime (struct CadetPeer *peer, | ||
1510 | struct GNUNET_TIME_AbsoluteNBO monotime) | ||
1511 | { | ||
1512 | |||
1513 | struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime); | ||
1514 | |||
1515 | if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us)) | ||
1516 | { | ||
1517 | peer->last_connection_create = mt; | ||
1518 | return GNUNET_YES; | ||
1519 | } | ||
1520 | return GNUNET_NO; | ||
1521 | } | ||
1522 | |||
1523 | |||
1524 | /** | ||
1525 | * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage. | ||
1526 | * | ||
1527 | * @param peer The peer that signed the monotime value. | ||
1528 | * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value. | ||
1529 | * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not. | ||
1530 | */ | ||
1531 | int | ||
1532 | GCP_check_monotime_sig (struct CadetPeer *peer, | ||
1533 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
1534 | { | ||
1535 | struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl ( | ||
1536 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR), | ||
1537 | .purpose.size = htonl (sizeof(cp)), | ||
1538 | .monotonic_time = msg->monotime}; | ||
1539 | |||
1540 | if (GNUNET_OK != | ||
1541 | GNUNET_CRYPTO_eddsa_verify ( | ||
1542 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR, | ||
1543 | &cp, | ||
1544 | &msg->monotime_sig, | ||
1545 | &peer->pid.public_key)) | ||
1546 | { | ||
1547 | GNUNET_break_op (0); | ||
1548 | return GNUNET_SYSERR; | ||
1549 | } | ||
1550 | return GNUNET_OK; | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /* end of gnunet-service-cadet-new_peer.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_peer.h b/src/service/cadet/gnunet-service-cadet_peer.h new file mode 100644 index 000000000..4c5ad4252 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_peer.h | |||
@@ -0,0 +1,433 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.h | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_PEER_H | ||
28 | #define GNUNET_SERVICE_CADET_PEER_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Get the static string for a peer ID. | ||
36 | * | ||
37 | * @param peer Peer. | ||
38 | * | ||
39 | * @return Static string for it's ID. | ||
40 | */ | ||
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 | * The 'desirability_table.c' program can be used to compute a list of | ||
66 | * sample outputs for different scenarios. Basically, we score paths | ||
67 | * lower if there are many alternatives, and higher if they are | ||
68 | * shorter than average, and very high if they are much shorter than | ||
69 | * average and without many alternatives. | ||
70 | * | ||
71 | * @param cp a peer reachable via a path | ||
72 | * @param off offset of @a cp in a path | ||
73 | * @return score how useful a path is to reach @a cp, | ||
74 | * positive scores mean path is more desirable | ||
75 | */ | ||
76 | double | ||
77 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
78 | unsigned int off); | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Obtain the peer identity for a `struct CadetPeer`. | ||
83 | * | ||
84 | * @param cp our peer handle | ||
85 | * @return the peer identity | ||
86 | */ | ||
87 | const struct GNUNET_PeerIdentity * | ||
88 | GCP_get_id (struct CadetPeer *cp); | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Iterate over all known peers. | ||
93 | * | ||
94 | * @param iter Iterator. | ||
95 | * @param cls Closure for @c iter. | ||
96 | */ | ||
97 | void | ||
98 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
99 | void *cls); | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Count the number of known paths toward the peer. | ||
104 | * | ||
105 | * @param cp Peer to get path info. | ||
106 | * @return Number of known paths. | ||
107 | */ | ||
108 | unsigned int | ||
109 | GCP_count_paths (const struct CadetPeer *cp); | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Drop all paths owned by this peer, and do not | ||
114 | * allow new ones to be added: We are shutting down. | ||
115 | * | ||
116 | * @param cp peer to drop paths to | ||
117 | */ | ||
118 | void | ||
119 | GCP_drop_owned_paths (struct CadetPeer *cp); | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Peer path iterator. | ||
124 | * | ||
125 | * @param cls Closure. | ||
126 | * @param path Path itself | ||
127 | * @param off offset of the target peer in @a path | ||
128 | * @return #GNUNET_YES if should keep iterating. | ||
129 | * #GNUNET_NO otherwise. | ||
130 | */ | ||
131 | typedef int | ||
132 | (*GCP_PathIterator) (void *cls, | ||
133 | struct CadetPeerPath *path, | ||
134 | unsigned int off); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Iterate over the paths to a peer. | ||
139 | * | ||
140 | * @param cp Peer to get path info. | ||
141 | * @param callback Function to call for every path. | ||
142 | * @param callback_cls Closure for @a callback. | ||
143 | * @return Number of iterated paths. | ||
144 | */ | ||
145 | unsigned int | ||
146 | GCP_iterate_paths (struct CadetPeer *cp, | ||
147 | GCP_PathIterator callback, | ||
148 | void *callback_cls); | ||
149 | |||
150 | /** | ||
151 | * Iterate over the paths to a peer without direct link. | ||
152 | * | ||
153 | * @param cp Peer to get path info. | ||
154 | * @param callback Function to call for every path. | ||
155 | * @param callback_cls Closure for @a callback. | ||
156 | * @return Number of iterated paths. | ||
157 | */ | ||
158 | unsigned int | ||
159 | GCP_iterate_indirect_paths (struct CadetPeer *cp, | ||
160 | GCP_PathIterator callback, | ||
161 | void *callback_cls); | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Iterate over the paths to @a peer where | ||
166 | * @a peer is at distance @a dist from us. | ||
167 | * | ||
168 | * @param cp Peer to get path info. | ||
169 | * @param dist desired distance of @a peer to us on the path | ||
170 | * @param callback Function to call for every path. | ||
171 | * @param callback_cls Closure for @a callback. | ||
172 | * @return Number of iterated paths. | ||
173 | */ | ||
174 | unsigned int | ||
175 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
176 | unsigned int dist, | ||
177 | GCP_PathIterator callback, | ||
178 | void *callback_cls); | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
183 | * | ||
184 | * @param cp peer to modify | ||
185 | * @param entry an entry on a path | ||
186 | * @param off offset of this peer on the path | ||
187 | */ | ||
188 | void | ||
189 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
190 | struct CadetPeerPathEntry *entry, | ||
191 | unsigned int off); | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
196 | * | ||
197 | * @param cp peer to modify | ||
198 | * @param entry an entry on a path | ||
199 | * @param off offset of this peer on the path | ||
200 | */ | ||
201 | void | ||
202 | GCP_path_entry_add (struct CadetPeer *cp, | ||
203 | struct CadetPeerPathEntry *entry, | ||
204 | unsigned int off); | ||
205 | |||
206 | |||
207 | /** | ||
208 | * Get the tunnel towards a peer. | ||
209 | * | ||
210 | * @param cp Peer to get from. | ||
211 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
212 | * @return Tunnel towards peer. | ||
213 | */ | ||
214 | struct CadetTunnel * | ||
215 | GCP_get_tunnel (struct CadetPeer *cp, | ||
216 | int create); | ||
217 | |||
218 | |||
219 | /** | ||
220 | * The tunnel to the given peer no longer exists, remove it from our | ||
221 | * data structures, and possibly clean up the peer itself. | ||
222 | * | ||
223 | * @param cp the peer affected | ||
224 | * @param t the dead tunnel | ||
225 | */ | ||
226 | void | ||
227 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
228 | struct CadetTunnel *t); | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Try adding a @a path to this @a cp. If the peer already | ||
233 | * has plenty of paths, return NULL. | ||
234 | * | ||
235 | * @param cp peer to which the @a path leads to | ||
236 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
237 | * @param off offset of @a cp in @a path | ||
238 | * @param force force attaching the path | ||
239 | * @return NULL if this peer does not care to become a new owner, | ||
240 | * otherwise the node in the peer's path heap for the @a path. | ||
241 | */ | ||
242 | struct GNUNET_CONTAINER_HeapNode * | ||
243 | GCP_attach_path (struct CadetPeer *cp, | ||
244 | struct CadetPeerPath *path, | ||
245 | unsigned int off, | ||
246 | int force); | ||
247 | |||
248 | |||
249 | /** | ||
250 | * This peer can no longer own @a path as the path | ||
251 | * has been extended and a peer further down the line | ||
252 | * is now the new owner. | ||
253 | * | ||
254 | * @param cp old owner of the @a path | ||
255 | * @param path path where the ownership is lost | ||
256 | * @param hn note in @a cp's path heap that must be deleted | ||
257 | */ | ||
258 | void | ||
259 | GCP_detach_path (struct CadetPeer *cp, | ||
260 | struct CadetPeerPath *path, | ||
261 | struct GNUNET_CONTAINER_HeapNode *hn); | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Add a @a connection to this @a cp. | ||
266 | * | ||
267 | * @param cp peer via which the @a connection goes | ||
268 | * @param cc the connection to add | ||
269 | */ | ||
270 | void | ||
271 | GCP_add_connection (struct CadetPeer *cp, | ||
272 | struct CadetConnection *cc); | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Remove a @a connection that went via this @a cp. | ||
277 | * | ||
278 | * @param cp peer via which the @a connection went | ||
279 | * @param cc the connection to remove | ||
280 | */ | ||
281 | void | ||
282 | GCP_remove_connection (struct CadetPeer *cp, | ||
283 | struct CadetConnection *cc); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * We got a HELLO for a @a cp, remember it, and possibly | ||
288 | * trigger adequate actions (like trying to connect). | ||
289 | * | ||
290 | * @param cp the peer we got a HELLO for | ||
291 | * @param hello the HELLO to remember | ||
292 | */ | ||
293 | void | ||
294 | GCP_set_hello (struct CadetPeer *cp, | ||
295 | const struct GNUNET_MessageHeader *hello); | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Clean up all entries about all peers. | ||
300 | * Must only be called after all tunnels, CORE-connections and | ||
301 | * connections are down. | ||
302 | */ | ||
303 | void | ||
304 | GCP_destroy_all_peers (void); | ||
305 | |||
306 | |||
307 | /** | ||
308 | * Data structure used to track whom we have to notify about changes | ||
309 | * in our ability to transmit to a given peer. | ||
310 | * | ||
311 | * All queue managers will be given equal chance for sending messages | ||
312 | * to @a cp. This construct this guarantees fairness for access to @a | ||
313 | * cp among the different message queues. Each connection or route | ||
314 | * will have its respective message queue managers for each direction. | ||
315 | */ | ||
316 | struct GCP_MessageQueueManager; | ||
317 | |||
318 | |||
319 | /** | ||
320 | * Function to call with updated message queue object. | ||
321 | * | ||
322 | * @param cls closure | ||
323 | * @param available #GNUNET_YES if sending is now possible, | ||
324 | * #GNUNET_NO if sending is no longer possible | ||
325 | * #GNUNET_SYSERR if sending is no longer possible | ||
326 | * and the last envelope was discarded | ||
327 | */ | ||
328 | typedef void | ||
329 | (*GCP_MessageQueueNotificationCallback)(void *cls, | ||
330 | int available); | ||
331 | |||
332 | |||
333 | /** | ||
334 | * Start message queue change notifications. Will create a new slot | ||
335 | * to manage the message queue to the given @a cp. | ||
336 | * | ||
337 | * @param cp peer to notify for | ||
338 | * @param cb function to call if mq becomes available or unavailable | ||
339 | * @param cb_cls closure for @a cb | ||
340 | * @return handle to cancel request | ||
341 | */ | ||
342 | struct GCP_MessageQueueManager * | ||
343 | GCP_request_mq (struct CadetPeer *cp, | ||
344 | GCP_MessageQueueNotificationCallback cb, | ||
345 | void *cb_cls); | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Test if @a cp has a core-level connection | ||
350 | * | ||
351 | * @param cp peer to test | ||
352 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
353 | */ | ||
354 | int | ||
355 | GCP_has_core_connection (struct CadetPeer *cp); | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Send the message in @a env via a @a mqm. Must only be called at | ||
360 | * most once after the respective | ||
361 | * #GCP_MessageQueueNotificationCallback was called with `available` | ||
362 | * set to #GNUNET_YES, and not after the callback was called with | ||
363 | * `available` set to #GNUNET_NO or #GNUNET_SYSERR. | ||
364 | * | ||
365 | * @param mqm message queue manager for the transmission | ||
366 | * @param env envelope with the message to send; must NOT | ||
367 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
368 | */ | ||
369 | void | ||
370 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
371 | struct GNUNET_MQ_Envelope *env); | ||
372 | |||
373 | |||
374 | /** | ||
375 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
376 | * This function should only be used to send error messages outside | ||
377 | * of flow and congestion control, similar to ICMP. Note that | ||
378 | * the envelope may be silently discarded as well. | ||
379 | * | ||
380 | * @param cp peer to send the message to | ||
381 | * @param env envelope with the message to send | ||
382 | */ | ||
383 | void | ||
384 | GCP_send_ooo (struct CadetPeer *cp, | ||
385 | struct GNUNET_MQ_Envelope *env); | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Stops message queue change notifications and sends a last message. | ||
390 | * In practice, this is implemented by sending that @a last_env | ||
391 | * message immediately (if any), ignoring queue order. | ||
392 | * | ||
393 | * @param mqm handle matching request to cancel | ||
394 | * @param last_env final message to transmit, or NULL | ||
395 | */ | ||
396 | void | ||
397 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
398 | struct GNUNET_MQ_Envelope *last_env); | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
403 | * | ||
404 | * @param cp peer to modify | ||
405 | * @param mq message queue to set (can be NULL) | ||
406 | */ | ||
407 | void | ||
408 | GCP_set_mq (struct CadetPeer *cp, | ||
409 | struct GNUNET_MQ_Handle *mq); | ||
410 | |||
411 | /** | ||
412 | * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage. | ||
413 | * | ||
414 | * @param peer The peer that signed the monotime value. | ||
415 | * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value. | ||
416 | * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not. | ||
417 | */ | ||
418 | int | ||
419 | GCP_check_monotime_sig (struct CadetPeer *peer, const struct | ||
420 | GNUNET_CADET_ConnectionCreateMessage *msg); | ||
421 | |||
422 | /** | ||
423 | * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer. | ||
424 | * | ||
425 | * @param peer The peer we received a new time value from. | ||
426 | * @param monotime Time value we check against the last time value we received from a peer. | ||
427 | * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer. | ||
428 | */ | ||
429 | int | ||
430 | GCP_check_and_update_monotime (struct CadetPeer *peer, | ||
431 | struct GNUNET_TIME_AbsoluteNBO monotime); | ||
432 | |||
433 | #endif | ||
diff --git a/src/service/cadet/gnunet-service-cadet_tunnels.c b/src/service/cadet/gnunet-service-cadet_tunnels.c new file mode 100644 index 000000000..c7e422926 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_tunnels.c | |||
@@ -0,0 +1,3668 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_tunnels.c | ||
22 | * @brief Information we track per tunnel. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * FIXME: | ||
27 | * - proper connection evaluation during connection management: | ||
28 | * + consider quality (or quality spread?) of current connection set | ||
29 | * when deciding how often to do maintenance | ||
30 | * + interact with PEER to drive DHT GET/PUT operations based | ||
31 | * on how much we like our connections | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet_util_lib.h" | ||
35 | #include "gnunet_statistics_service.h" | ||
36 | #include "gnunet_signatures.h" | ||
37 | #include "cadet_protocol.h" | ||
38 | #include "gnunet-service-cadet_channel.h" | ||
39 | #include "gnunet-service-cadet_connection.h" | ||
40 | #include "gnunet-service-cadet_tunnels.h" | ||
41 | #include "gnunet-service-cadet_peer.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
43 | |||
44 | |||
45 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-tun", __VA_ARGS__) | ||
46 | |||
47 | /** | ||
48 | * How often do we try to decrypt payload with unverified key | ||
49 | * material? Used to limit CPU increase upon receiving bogus | ||
50 | * KX. | ||
51 | */ | ||
52 | #define MAX_UNVERIFIED_ATTEMPTS 16 | ||
53 | |||
54 | /** | ||
55 | * How long do we wait until tearing down an idle tunnel? | ||
56 | */ | ||
57 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply ( \ | ||
58 | GNUNET_TIME_UNIT_SECONDS, 90) | ||
59 | |||
60 | /** | ||
61 | * How long do we wait initially before retransmitting the KX? | ||
62 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! | ||
63 | */ | ||
64 | #define INITIAL_KX_RETRY_DELAY GNUNET_TIME_relative_multiply ( \ | ||
65 | GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
66 | |||
67 | /** | ||
68 | * Maximum number of skipped keys we keep in memory per tunnel. | ||
69 | */ | ||
70 | #define MAX_SKIPPED_KEYS 64 | ||
71 | |||
72 | /** | ||
73 | * Maximum number of keys (and thus ratchet steps) we are willing to | ||
74 | * skip before we decide this is either a bogus packet or a DoS-attempt. | ||
75 | */ | ||
76 | #define MAX_KEY_GAP 256 | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Struct to old keys for skipped messages while advancing the Axolotl ratchet. | ||
81 | */ | ||
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 @e HKr) are kept in the @e skipped_head DLL. | ||
173 | */ | ||
174 | struct GNUNET_CRYPTO_SymmetricSessionKey CKr; | ||
175 | |||
176 | /** | ||
177 | * ECDH for key exchange (A0 / B0). | ||
178 | */ | ||
179 | struct GNUNET_CRYPTO_EcdhePrivateKey kx_0; | ||
180 | |||
181 | /** | ||
182 | * ECDH Ratchet key (our private key in the current DH). | ||
183 | */ | ||
184 | struct GNUNET_CRYPTO_EcdhePrivateKey DHRs; | ||
185 | |||
186 | /** | ||
187 | * ECDH Ratchet key (other peer's public key in the current DH). | ||
188 | */ | ||
189 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; | ||
190 | |||
191 | /** | ||
192 | * Last ephemeral public key received from the other peer, | ||
193 | * for duplicate detection. | ||
194 | */ | ||
195 | struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral; | ||
196 | |||
197 | /** | ||
198 | * Time when the current ratchet expires and a new one is triggered | ||
199 | * (if @e ratchet_allowed is #GNUNET_YES). | ||
200 | */ | ||
201 | struct GNUNET_TIME_Absolute ratchet_expiration; | ||
202 | |||
203 | /** | ||
204 | * Number of elements in @a skipped_head <-> @a skipped_tail. | ||
205 | */ | ||
206 | unsigned int skipped; | ||
207 | |||
208 | /** | ||
209 | * Message number (reset to 0 with each new ratchet, next message to send). | ||
210 | */ | ||
211 | uint32_t Ns; | ||
212 | |||
213 | /** | ||
214 | * Message number (reset to 0 with each new ratchet, next message to recv). | ||
215 | */ | ||
216 | uint32_t Nr; | ||
217 | |||
218 | /** | ||
219 | * Previous message numbers (# of msgs sent under prev ratchet) | ||
220 | */ | ||
221 | uint32_t PNs; | ||
222 | |||
223 | /** | ||
224 | * True (#GNUNET_YES) if we have to send a new ratchet key in next msg. | ||
225 | */ | ||
226 | int ratchet_flag; | ||
227 | |||
228 | /** | ||
229 | * True (#GNUNET_YES) if we have received a message from the | ||
230 | * other peer that uses the keys from our last ratchet step. | ||
231 | * This implies that we are again allowed to advance the ratchet, | ||
232 | * otherwise we have to wait until the other peer sees our current | ||
233 | * ephemeral key and advances first. | ||
234 | * | ||
235 | * #GNUNET_NO if we have advanced the ratched but lack any evidence | ||
236 | * that the other peer has noticed this. | ||
237 | */ | ||
238 | int ratchet_allowed; | ||
239 | |||
240 | /** | ||
241 | * Number of messages received since our last ratchet advance. | ||
242 | * | ||
243 | * If this counter = 0, we cannot send a new ratchet key in the next | ||
244 | * message. | ||
245 | * | ||
246 | * If this counter > 0, we could (but don't have to) send a new key. | ||
247 | * | ||
248 | * Once the @e ratchet_counter is larger than | ||
249 | * #ratchet_messages (or @e ratchet_expiration time has past), and | ||
250 | * @e ratchet_allowed is #GNUNET_YES, we advance the ratchet. | ||
251 | */ | ||
252 | unsigned int ratchet_counter; | ||
253 | }; | ||
254 | |||
255 | |||
256 | /** | ||
257 | * Struct used to save messages in a non-ready tunnel to send once connected. | ||
258 | */ | ||
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 | unsigned int | ||
580 | GCT_count_channels (struct CadetTunnel *t) | ||
581 | { | ||
582 | return GNUNET_CONTAINER_multihashmap32_size (t->channels); | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Lookup a channel by its @a ctn. | ||
588 | * | ||
589 | * @param t tunnel to look in | ||
590 | * @param ctn number of channel to find | ||
591 | * @return NULL if channel does not exist | ||
592 | */ | ||
593 | struct CadetChannel * | ||
594 | lookup_channel (struct CadetTunnel *t, | ||
595 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
596 | { | ||
597 | return GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
598 | ntohl (ctn.cn)); | ||
599 | } | ||
600 | |||
601 | |||
602 | unsigned int | ||
603 | GCT_count_any_connections (const struct CadetTunnel *t) | ||
604 | { | ||
605 | return t->num_ready_connections + t->num_busy_connections; | ||
606 | } | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Find first connection that is ready in the list of | ||
611 | * our connections. Picks ready connections round-robin. | ||
612 | * | ||
613 | * @param t tunnel to search | ||
614 | * @return NULL if we have no connection that is ready | ||
615 | */ | ||
616 | static struct CadetTConnection * | ||
617 | get_ready_connection (struct CadetTunnel *t) | ||
618 | { | ||
619 | struct CadetTConnection *hd = t->connection_ready_head; | ||
620 | |||
621 | GNUNET_assert ((NULL == hd) || | ||
622 | (GNUNET_YES == hd->is_ready)); | ||
623 | return hd; | ||
624 | } | ||
625 | |||
626 | |||
627 | /** | ||
628 | * Get the encryption state of a tunnel. | ||
629 | * | ||
630 | * @param t Tunnel. | ||
631 | * | ||
632 | * @return Tunnel's encryption state. | ||
633 | */ | ||
634 | enum CadetTunnelEState | ||
635 | GCT_get_estate (struct CadetTunnel *t) | ||
636 | { | ||
637 | return t->estate; | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Called when either we have a new connection, or a new message in the | ||
643 | * queue, or some existing connection has transmission capacity. Looks | ||
644 | * at our message queue and if there is a message, picks a connection | ||
645 | * to send it on. | ||
646 | * | ||
647 | * @param cls the `struct CadetTunnel` to process messages on | ||
648 | */ | ||
649 | static void | ||
650 | trigger_transmissions (void *cls); | ||
651 | |||
652 | |||
653 | /* ************************************** start core crypto ***************************** */ | ||
654 | |||
655 | |||
656 | /** | ||
657 | * Create a new Axolotl ephemeral (ratchet) key. | ||
658 | * | ||
659 | * @param ax key material to update | ||
660 | */ | ||
661 | static void | ||
662 | new_ephemeral (struct CadetTunnelAxolotl *ax) | ||
663 | { | ||
664 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
665 | "Creating new ephemeral ratchet key (DHRs)\n"); | ||
666 | GNUNET_CRYPTO_ecdhe_key_create (&ax->DHRs); | ||
667 | } | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Calculate HMAC. | ||
672 | * | ||
673 | * @param plaintext Content to HMAC. | ||
674 | * @param size Size of @c plaintext. | ||
675 | * @param iv Initialization vector for the message. | ||
676 | * @param key Key to use. | ||
677 | * @param[out] hmac Destination to store the HMAC. | ||
678 | */ | ||
679 | static void | ||
680 | t_hmac (const void *plaintext, | ||
681 | size_t size, | ||
682 | uint32_t iv, | ||
683 | const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
684 | struct GNUNET_ShortHashCode *hmac) | ||
685 | { | ||
686 | static const char ctx[] = "cadet authentication key"; | ||
687 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
688 | struct GNUNET_HashCode hash; | ||
689 | |||
690 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
691 | key, | ||
692 | &iv, sizeof(iv), | ||
693 | key, sizeof(*key), | ||
694 | ctx, sizeof(ctx), | ||
695 | NULL); | ||
696 | /* Two step: GNUNET_ShortHash is only 256 bits, | ||
697 | GNUNET_HashCode is 512, so we truncate. */ | ||
698 | GNUNET_CRYPTO_hmac (&auth_key, | ||
699 | plaintext, | ||
700 | size, | ||
701 | &hash); | ||
702 | GNUNET_memcpy (hmac, | ||
703 | &hash, | ||
704 | sizeof(*hmac)); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * Perform a HMAC. | ||
710 | * | ||
711 | * @param key Key to use. | ||
712 | * @param[out] hash Resulting HMAC. | ||
713 | * @param source Source key material (data to HMAC). | ||
714 | * @param len Length of @a source. | ||
715 | */ | ||
716 | static void | ||
717 | t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
718 | struct GNUNET_HashCode *hash, | ||
719 | const void *source, | ||
720 | unsigned int len) | ||
721 | { | ||
722 | static const char ctx[] = "axolotl HMAC-HASH"; | ||
723 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
724 | |||
725 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
726 | key, | ||
727 | ctx, sizeof(ctx), | ||
728 | NULL); | ||
729 | GNUNET_CRYPTO_hmac (&auth_key, | ||
730 | source, | ||
731 | len, | ||
732 | hash); | ||
733 | } | ||
734 | |||
735 | |||
736 | /** | ||
737 | * Derive a symmetric encryption key from an HMAC-HASH. | ||
738 | * | ||
739 | * @param key Key to use for the HMAC. | ||
740 | * @param[out] out Key to generate. | ||
741 | * @param source Source key material (data to HMAC). | ||
742 | * @param len Length of @a source. | ||
743 | */ | ||
744 | static void | ||
745 | t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
746 | struct GNUNET_CRYPTO_SymmetricSessionKey *out, | ||
747 | const void *source, | ||
748 | unsigned int len) | ||
749 | { | ||
750 | static const char ctx[] = "axolotl derive key"; | ||
751 | struct GNUNET_HashCode h; | ||
752 | |||
753 | t_ax_hmac_hash (key, | ||
754 | &h, | ||
755 | source, | ||
756 | len); | ||
757 | GNUNET_CRYPTO_kdf (out, sizeof(*out), | ||
758 | ctx, sizeof(ctx), | ||
759 | &h, sizeof(h), | ||
760 | NULL); | ||
761 | } | ||
762 | |||
763 | |||
764 | /** | ||
765 | * Encrypt data with the axolotl tunnel key. | ||
766 | * | ||
767 | * @param ax key material to use. | ||
768 | * @param dst Destination with @a size bytes for the encrypted data. | ||
769 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes | ||
770 | * @param size Size of the buffers at @a src and @a dst | ||
771 | */ | ||
772 | static void | ||
773 | t_ax_encrypt (struct CadetTunnelAxolotl *ax, | ||
774 | void *dst, | ||
775 | const void *src, | ||
776 | size_t size) | ||
777 | { | ||
778 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
779 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
780 | size_t out_size; | ||
781 | |||
782 | ax->ratchet_counter++; | ||
783 | if ((GNUNET_YES == ax->ratchet_allowed) && | ||
784 | ((ratchet_messages <= ax->ratchet_counter) || | ||
785 | (0 == GNUNET_TIME_absolute_get_remaining ( | ||
786 | ax->ratchet_expiration).rel_value_us))) | ||
787 | { | ||
788 | ax->ratchet_flag = GNUNET_YES; | ||
789 | } | ||
790 | if (GNUNET_YES == ax->ratchet_flag) | ||
791 | { | ||
792 | /* Advance ratchet */ | ||
793 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; | ||
794 | struct GNUNET_HashCode dh; | ||
795 | struct GNUNET_HashCode hmac; | ||
796 | static const char ctx[] = "axolotl ratchet"; | ||
797 | |||
798 | new_ephemeral (ax); | ||
799 | ax->HKs = ax->NHKs; | ||
800 | |||
801 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | ||
802 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, | ||
803 | &ax->DHRr, | ||
804 | &dh); | ||
805 | t_ax_hmac_hash (&ax->RK, | ||
806 | &hmac, | ||
807 | &dh, | ||
808 | sizeof(dh)); | ||
809 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
810 | ctx, sizeof(ctx), | ||
811 | &hmac, sizeof(hmac), | ||
812 | NULL); | ||
813 | ax->RK = keys[0]; | ||
814 | ax->NHKs = keys[1]; | ||
815 | ax->CKs = keys[2]; | ||
816 | |||
817 | ax->PNs = ax->Ns; | ||
818 | ax->Ns = 0; | ||
819 | ax->ratchet_flag = GNUNET_NO; | ||
820 | ax->ratchet_allowed = GNUNET_NO; | ||
821 | ax->ratchet_counter = 0; | ||
822 | ax->ratchet_expiration | ||
823 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
824 | ratchet_time); | ||
825 | } | ||
826 | |||
827 | t_hmac_derive_key (&ax->CKs, | ||
828 | &MK, | ||
829 | "0", | ||
830 | 1); | ||
831 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
832 | &MK, | ||
833 | NULL, 0, | ||
834 | NULL); | ||
835 | |||
836 | out_size = GNUNET_CRYPTO_symmetric_encrypt (src, | ||
837 | size, | ||
838 | &MK, | ||
839 | &iv, | ||
840 | dst); | ||
841 | GNUNET_assert (size == out_size); | ||
842 | t_hmac_derive_key (&ax->CKs, | ||
843 | &ax->CKs, | ||
844 | "1", | ||
845 | 1); | ||
846 | } | ||
847 | |||
848 | |||
849 | /** | ||
850 | * Decrypt data with the axolotl tunnel key. | ||
851 | * | ||
852 | * @param ax key material to use. | ||
853 | * @param dst Destination for the decrypted data, must contain @a size bytes. | ||
854 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. | ||
855 | * @param size Size of the @a src and @a dst buffers | ||
856 | */ | ||
857 | static void | ||
858 | t_ax_decrypt (struct CadetTunnelAxolotl *ax, | ||
859 | void *dst, | ||
860 | const void *src, | ||
861 | size_t size) | ||
862 | { | ||
863 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
864 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
865 | size_t out_size; | ||
866 | |||
867 | t_hmac_derive_key (&ax->CKr, | ||
868 | &MK, | ||
869 | "0", | ||
870 | 1); | ||
871 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
872 | &MK, | ||
873 | NULL, 0, | ||
874 | NULL); | ||
875 | GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader)); | ||
876 | out_size = GNUNET_CRYPTO_symmetric_decrypt (src, | ||
877 | size, | ||
878 | &MK, | ||
879 | &iv, | ||
880 | dst); | ||
881 | GNUNET_assert (out_size == size); | ||
882 | t_hmac_derive_key (&ax->CKr, | ||
883 | &ax->CKr, | ||
884 | "1", | ||
885 | 1); | ||
886 | } | ||
887 | |||
888 | |||
889 | /** | ||
890 | * Encrypt header with the axolotl header key. | ||
891 | * | ||
892 | * @param ax key material to use. | ||
893 | * @param[in,out] msg Message whose header to encrypt. | ||
894 | */ | ||
895 | static void | ||
896 | t_h_encrypt (struct CadetTunnelAxolotl *ax, | ||
897 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
898 | { | ||
899 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
900 | size_t out_size; | ||
901 | |||
902 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
903 | &ax->HKs, | ||
904 | NULL, 0, | ||
905 | NULL); | ||
906 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header, | ||
907 | sizeof(struct | ||
908 | GNUNET_CADET_AxHeader), | ||
909 | &ax->HKs, | ||
910 | &iv, | ||
911 | &msg->ax_header); | ||
912 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size); | ||
913 | } | ||
914 | |||
915 | |||
916 | /** | ||
917 | * Decrypt header with the current axolotl header key. | ||
918 | * | ||
919 | * @param ax key material to use. | ||
920 | * @param src Message whose header to decrypt. | ||
921 | * @param dst Where to decrypt header to. | ||
922 | */ | ||
923 | static void | ||
924 | t_h_decrypt (struct CadetTunnelAxolotl *ax, | ||
925 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
926 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) | ||
927 | { | ||
928 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
929 | size_t out_size; | ||
930 | |||
931 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
932 | &ax->HKr, | ||
933 | NULL, 0, | ||
934 | NULL); | ||
935 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, | ||
936 | sizeof(struct | ||
937 | GNUNET_CADET_AxHeader), | ||
938 | &ax->HKr, | ||
939 | &iv, | ||
940 | &dst->ax_header.Ns); | ||
941 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size); | ||
942 | } | ||
943 | |||
944 | |||
945 | /** | ||
946 | * Delete a key from the list of skipped keys. | ||
947 | * | ||
948 | * @param ax key material to delete @a key from. | ||
949 | * @param key Key to delete. | ||
950 | */ | ||
951 | static void | ||
952 | delete_skipped_key (struct CadetTunnelAxolotl *ax, | ||
953 | struct CadetTunnelSkippedKey *key) | ||
954 | { | ||
955 | GNUNET_CONTAINER_DLL_remove (ax->skipped_head, | ||
956 | ax->skipped_tail, | ||
957 | key); | ||
958 | GNUNET_free (key); | ||
959 | ax->skipped--; | ||
960 | } | ||
961 | |||
962 | |||
963 | /** | ||
964 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
965 | * data has not been altered since it was sent by the remote peer. | ||
966 | * | ||
967 | * @param ax key material to use. | ||
968 | * @param dst Destination for the plaintext. | ||
969 | * @param src Source of the message. Can overlap with @c dst. | ||
970 | * @param size Size of the message. | ||
971 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
972 | */ | ||
973 | static ssize_t | ||
974 | try_old_ax_keys (struct CadetTunnelAxolotl *ax, | ||
975 | void *dst, | ||
976 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
977 | size_t size) | ||
978 | { | ||
979 | struct CadetTunnelSkippedKey *key; | ||
980 | struct GNUNET_ShortHashCode *hmac; | ||
981 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
982 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
983 | struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; | ||
984 | size_t esize; | ||
985 | size_t res; | ||
986 | size_t len; | ||
987 | unsigned int N; | ||
988 | |||
989 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
990 | "Trying skipped keys\n"); | ||
991 | hmac = &plaintext_header.hmac; | ||
992 | esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
993 | |||
994 | /* Find a correct Header Key */ | ||
995 | valid_HK = NULL; | ||
996 | for (key = ax->skipped_head; NULL != key; key = key->next) | ||
997 | { | ||
998 | t_hmac (&src->ax_header, | ||
999 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1000 | 0, | ||
1001 | &key->HK, | ||
1002 | hmac); | ||
1003 | if (0 == GNUNET_memcmp (hmac, | ||
1004 | &src->hmac)) | ||
1005 | { | ||
1006 | valid_HK = &key->HK; | ||
1007 | break; | ||
1008 | } | ||
1009 | } | ||
1010 | if (NULL == key) | ||
1011 | return -1; | ||
1012 | |||
1013 | /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ | ||
1014 | GNUNET_assert (size > sizeof(struct GNUNET_CADET_TunnelEncryptedMessage)); | ||
1015 | len = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1016 | GNUNET_assert (len >= sizeof(struct GNUNET_MessageHeader)); | ||
1017 | |||
1018 | /* Decrypt header */ | ||
1019 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
1020 | &key->HK, | ||
1021 | NULL, 0, | ||
1022 | NULL); | ||
1023 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, | ||
1024 | sizeof(struct GNUNET_CADET_AxHeader), | ||
1025 | &key->HK, | ||
1026 | &iv, | ||
1027 | &plaintext_header.ax_header.Ns); | ||
1028 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == res); | ||
1029 | |||
1030 | /* Find the correct message key */ | ||
1031 | N = ntohl (plaintext_header.ax_header.Ns); | ||
1032 | while ((NULL != key) && | ||
1033 | (N != key->Kn)) | ||
1034 | key = key->next; | ||
1035 | if ((NULL == key) || | ||
1036 | (0 != GNUNET_memcmp (&key->HK, | ||
1037 | valid_HK))) | ||
1038 | return -1; | ||
1039 | |||
1040 | /* Decrypt payload */ | ||
1041 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
1042 | &key->MK, | ||
1043 | NULL, | ||
1044 | 0, | ||
1045 | NULL); | ||
1046 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], | ||
1047 | len, | ||
1048 | &key->MK, | ||
1049 | &iv, | ||
1050 | dst); | ||
1051 | delete_skipped_key (ax, | ||
1052 | key); | ||
1053 | return res; | ||
1054 | } | ||
1055 | |||
1056 | |||
1057 | /** | ||
1058 | * Delete a key from the list of skipped keys. | ||
1059 | * | ||
1060 | * @param ax key material to delete from. | ||
1061 | * @param HKr Header Key to use. | ||
1062 | */ | ||
1063 | static void | ||
1064 | store_skipped_key (struct CadetTunnelAxolotl *ax, | ||
1065 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | ||
1066 | { | ||
1067 | struct CadetTunnelSkippedKey *key; | ||
1068 | |||
1069 | key = GNUNET_new (struct CadetTunnelSkippedKey); | ||
1070 | key->timestamp = GNUNET_TIME_absolute_get (); | ||
1071 | key->Kn = ax->Nr; | ||
1072 | key->HK = ax->HKr; | ||
1073 | t_hmac_derive_key (&ax->CKr, | ||
1074 | &key->MK, | ||
1075 | "0", | ||
1076 | 1); | ||
1077 | t_hmac_derive_key (&ax->CKr, | ||
1078 | &ax->CKr, | ||
1079 | "1", | ||
1080 | 1); | ||
1081 | GNUNET_CONTAINER_DLL_insert (ax->skipped_head, | ||
1082 | ax->skipped_tail, | ||
1083 | key); | ||
1084 | ax->skipped++; | ||
1085 | ax->Nr++; | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | /** | ||
1090 | * Stage skipped AX keys and calculate the message key. | ||
1091 | * Stores each HK and MK for skipped messages. | ||
1092 | * | ||
1093 | * @param ax key material to use | ||
1094 | * @param HKr Header key. | ||
1095 | * @param Np Received meesage number. | ||
1096 | * @return #GNUNET_OK if keys were stored. | ||
1097 | * #GNUNET_SYSERR if an error occurred (@a Np not expected). | ||
1098 | */ | ||
1099 | static int | ||
1100 | store_ax_keys (struct CadetTunnelAxolotl *ax, | ||
1101 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | ||
1102 | uint32_t Np) | ||
1103 | { | ||
1104 | int gap; | ||
1105 | |||
1106 | gap = Np - ax->Nr; | ||
1107 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1108 | "Storing skipped keys [%u, %u)\n", | ||
1109 | ax->Nr, | ||
1110 | Np); | ||
1111 | if (MAX_KEY_GAP < gap) | ||
1112 | { | ||
1113 | /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */ | ||
1114 | /* TODO: start new key exchange on return */ | ||
1115 | GNUNET_break_op (0); | ||
1116 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1117 | "Got message %u, expected %u+\n", | ||
1118 | Np, | ||
1119 | ax->Nr); | ||
1120 | return GNUNET_SYSERR; | ||
1121 | } | ||
1122 | if (0 > gap) | ||
1123 | { | ||
1124 | /* Delayed message: don't store keys, flag to try old keys. */ | ||
1125 | return GNUNET_SYSERR; | ||
1126 | } | ||
1127 | |||
1128 | while (ax->Nr < Np) | ||
1129 | store_skipped_key (ax, | ||
1130 | HKr); | ||
1131 | |||
1132 | while (ax->skipped > MAX_SKIPPED_KEYS) | ||
1133 | delete_skipped_key (ax, | ||
1134 | ax->skipped_tail); | ||
1135 | return GNUNET_OK; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | /** | ||
1140 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
1141 | * data has not been altered since it was sent by the remote peer. | ||
1142 | * | ||
1143 | * @param ax key material to use | ||
1144 | * @param dst Destination for the plaintext. | ||
1145 | * @param src Source of the message. Can overlap with @c dst. | ||
1146 | * @param size Size of the message. | ||
1147 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
1148 | */ | ||
1149 | static ssize_t | ||
1150 | t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax, | ||
1151 | void *dst, | ||
1152 | const struct | ||
1153 | GNUNET_CADET_TunnelEncryptedMessage *src, | ||
1154 | size_t size) | ||
1155 | { | ||
1156 | struct GNUNET_ShortHashCode msg_hmac; | ||
1157 | struct GNUNET_HashCode hmac; | ||
1158 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
1159 | uint32_t Np; | ||
1160 | uint32_t PNp; | ||
1161 | size_t esize; /* Size of encryped payload */ | ||
1162 | |||
1163 | esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1164 | |||
1165 | /* Try current HK */ | ||
1166 | t_hmac (&src->ax_header, | ||
1167 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1168 | 0, &ax->HKr, | ||
1169 | &msg_hmac); | ||
1170 | if (0 != GNUNET_memcmp (&msg_hmac, | ||
1171 | &src->hmac)) | ||
1172 | { | ||
1173 | static const char ctx[] = "axolotl ratchet"; | ||
1174 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */ | ||
1175 | struct GNUNET_CRYPTO_SymmetricSessionKey HK; | ||
1176 | struct GNUNET_HashCode dh; | ||
1177 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; | ||
1178 | |||
1179 | /* Try Next HK */ | ||
1180 | t_hmac (&src->ax_header, | ||
1181 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1182 | 0, | ||
1183 | &ax->NHKr, | ||
1184 | &msg_hmac); | ||
1185 | if (0 != GNUNET_memcmp (&msg_hmac, | ||
1186 | &src->hmac)) | ||
1187 | { | ||
1188 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1189 | return try_old_ax_keys (ax, | ||
1190 | dst, | ||
1191 | src, | ||
1192 | size); | ||
1193 | } | ||
1194 | HK = ax->HKr; | ||
1195 | ax->HKr = ax->NHKr; | ||
1196 | t_h_decrypt (ax, | ||
1197 | src, | ||
1198 | &plaintext_header); | ||
1199 | Np = ntohl (plaintext_header.ax_header.Ns); | ||
1200 | PNp = ntohl (plaintext_header.ax_header.PNs); | ||
1201 | DHRp = &plaintext_header.ax_header.DHRs; | ||
1202 | store_ax_keys (ax, | ||
1203 | &HK, | ||
1204 | PNp); | ||
1205 | |||
1206 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | ||
1207 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, | ||
1208 | DHRp, | ||
1209 | &dh); | ||
1210 | t_ax_hmac_hash (&ax->RK, | ||
1211 | &hmac, | ||
1212 | &dh, sizeof(dh)); | ||
1213 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
1214 | ctx, sizeof(ctx), | ||
1215 | &hmac, sizeof(hmac), | ||
1216 | NULL); | ||
1217 | |||
1218 | /* Commit "purported" keys */ | ||
1219 | ax->RK = keys[0]; | ||
1220 | ax->NHKr = keys[1]; | ||
1221 | ax->CKr = keys[2]; | ||
1222 | ax->DHRr = *DHRp; | ||
1223 | ax->Nr = 0; | ||
1224 | ax->ratchet_allowed = GNUNET_YES; | ||
1225 | } | ||
1226 | else | ||
1227 | { | ||
1228 | t_h_decrypt (ax, | ||
1229 | src, | ||
1230 | &plaintext_header); | ||
1231 | Np = ntohl (plaintext_header.ax_header.Ns); | ||
1232 | PNp = ntohl (plaintext_header.ax_header.PNs); | ||
1233 | } | ||
1234 | if ((Np != ax->Nr) && | ||
1235 | (GNUNET_OK != store_ax_keys (ax, | ||
1236 | &ax->HKr, | ||
1237 | Np))) | ||
1238 | { | ||
1239 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1240 | return try_old_ax_keys (ax, | ||
1241 | dst, | ||
1242 | src, | ||
1243 | size); | ||
1244 | } | ||
1245 | |||
1246 | t_ax_decrypt (ax, | ||
1247 | dst, | ||
1248 | &src[1], | ||
1249 | esize); | ||
1250 | ax->Nr = Np + 1; | ||
1251 | return esize; | ||
1252 | } | ||
1253 | |||
1254 | |||
1255 | /** | ||
1256 | * Our tunnel became ready for the first time, notify channels | ||
1257 | * that have been waiting. | ||
1258 | * | ||
1259 | * @param cls our tunnel, not used | ||
1260 | * @param key unique ID of the channel, not used | ||
1261 | * @param value the `struct CadetChannel` to notify | ||
1262 | * @return #GNUNET_OK (continue to iterate) | ||
1263 | */ | ||
1264 | static int | ||
1265 | notify_tunnel_up_cb (void *cls, | ||
1266 | uint32_t key, | ||
1267 | void *value) | ||
1268 | { | ||
1269 | struct CadetChannel *ch = value; | ||
1270 | |||
1271 | GCCH_tunnel_up (ch); | ||
1272 | return GNUNET_OK; | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | /** | ||
1277 | * Change the tunnel encryption state. | ||
1278 | * If the encryption state changes to OK, stop the rekey task. | ||
1279 | * | ||
1280 | * @param t Tunnel whose encryption state to change, or NULL. | ||
1281 | * @param state New encryption state. | ||
1282 | */ | ||
1283 | void | ||
1284 | GCT_change_estate (struct CadetTunnel *t, | ||
1285 | enum CadetTunnelEState state) | ||
1286 | { | ||
1287 | enum CadetTunnelEState old = t->estate; | ||
1288 | |||
1289 | t->estate = state; | ||
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "%s estate changed from %s to %s\n", | ||
1292 | GCT_2s (t), | ||
1293 | estate2s (old), | ||
1294 | estate2s (state)); | ||
1295 | |||
1296 | if ((CADET_TUNNEL_KEY_OK != old) && | ||
1297 | (CADET_TUNNEL_KEY_OK == t->estate)) | ||
1298 | { | ||
1299 | if (NULL != t->kx_task) | ||
1300 | { | ||
1301 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1302 | t->kx_task = NULL; | ||
1303 | } | ||
1304 | /* notify all channels that have been waiting */ | ||
1305 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
1306 | ¬ify_tunnel_up_cb, | ||
1307 | t); | ||
1308 | if (NULL != t->send_task) | ||
1309 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
1310 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
1311 | t); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | /** | ||
1317 | * Send a KX message. | ||
1318 | * | ||
1319 | * @param t tunnel on which to send the KX_AUTH | ||
1320 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if | ||
1321 | * we are to find one that is ready. | ||
1322 | * @param ax axolotl key context to use | ||
1323 | */ | ||
1324 | static void | ||
1325 | send_kx (struct CadetTunnel *t, | ||
1326 | struct CadetTConnection *ct, | ||
1327 | struct CadetTunnelAxolotl *ax) | ||
1328 | { | ||
1329 | struct CadetConnection *cc; | ||
1330 | struct GNUNET_MQ_Envelope *env; | ||
1331 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; | ||
1332 | enum GNUNET_CADET_KX_Flags flags; | ||
1333 | |||
1334 | if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination))) | ||
1335 | return; /* only Alice may send KX */ | ||
1336 | if ((NULL == ct) || | ||
1337 | (GNUNET_NO == ct->is_ready)) | ||
1338 | ct = get_ready_connection (t); | ||
1339 | if (NULL == ct) | ||
1340 | { | ||
1341 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1342 | "Wanted to send %s in state %s, but no connection is ready, deferring\n", | ||
1343 | GCT_2s (t), | ||
1344 | estate2s (t->estate)); | ||
1345 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1346 | return; | ||
1347 | } | ||
1348 | cc = ct->cc; | ||
1349 | env = GNUNET_MQ_msg (msg, | ||
1350 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); | ||
1351 | flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */ | ||
1352 | msg->flags = htonl (flags); | ||
1353 | msg->cid = *GCC_get_id (cc); | ||
1354 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | ||
1355 | &msg->ephemeral_key); | ||
1356 | #if DEBUG_KX | ||
1357 | msg->ephemeral_key_XXX = ax->kx_0; | ||
1358 | msg->private_key_XXX = *my_private_key; | ||
1359 | #endif | ||
1360 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1361 | "Sending KX message to %s with ephemeral %s on CID %s\n", | ||
1362 | GCT_2s (t), | ||
1363 | GNUNET_e2s (&msg->ephemeral_key), | ||
1364 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1365 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | ||
1366 | &msg->ratchet_key); | ||
1367 | mark_connection_unready (ct); | ||
1368 | t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | ||
1369 | t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | ||
1370 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
1371 | GCT_change_estate (t, | ||
1372 | CADET_TUNNEL_KEY_AX_SENT); | ||
1373 | else if (CADET_TUNNEL_KEY_AX_RECV == t->estate) | ||
1374 | GCT_change_estate (t, | ||
1375 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | ||
1376 | GCC_transmit (cc, | ||
1377 | env); | ||
1378 | GNUNET_STATISTICS_update (stats, | ||
1379 | "# KX transmitted", | ||
1380 | 1, | ||
1381 | GNUNET_NO); | ||
1382 | } | ||
1383 | |||
1384 | |||
1385 | /** | ||
1386 | * Send a KX_AUTH message. | ||
1387 | * | ||
1388 | * @param t tunnel on which to send the KX_AUTH | ||
1389 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if | ||
1390 | * we are to find one that is ready. | ||
1391 | * @param ax axolotl key context to use | ||
1392 | * @param force_reply Force the other peer to reply with a KX_AUTH message | ||
1393 | * (set if we would like to transmit right now, but cannot) | ||
1394 | */ | ||
1395 | static void | ||
1396 | send_kx_auth (struct CadetTunnel *t, | ||
1397 | struct CadetTConnection *ct, | ||
1398 | struct CadetTunnelAxolotl *ax, | ||
1399 | int force_reply) | ||
1400 | { | ||
1401 | struct CadetConnection *cc; | ||
1402 | struct GNUNET_MQ_Envelope *env; | ||
1403 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg; | ||
1404 | enum GNUNET_CADET_KX_Flags flags; | ||
1405 | |||
1406 | if ((NULL == ct) || | ||
1407 | (GNUNET_NO == ct->is_ready)) | ||
1408 | ct = get_ready_connection (t); | ||
1409 | if (NULL == ct) | ||
1410 | { | ||
1411 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1412 | "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n", | ||
1413 | GCT_2s (t)); | ||
1414 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1415 | t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */ | ||
1416 | return; | ||
1417 | } | ||
1418 | t->kx_auth_requested = GNUNET_NO; /* clear flag */ | ||
1419 | cc = ct->cc; | ||
1420 | env = GNUNET_MQ_msg (msg, | ||
1421 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH); | ||
1422 | flags = GNUNET_CADET_KX_FLAG_NONE; | ||
1423 | if (GNUNET_YES == force_reply) | ||
1424 | flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; | ||
1425 | msg->kx.flags = htonl (flags); | ||
1426 | msg->kx.cid = *GCC_get_id (cc); | ||
1427 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | ||
1428 | &msg->kx.ephemeral_key); | ||
1429 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | ||
1430 | &msg->kx.ratchet_key); | ||
1431 | #if DEBUG_KX | ||
1432 | msg->kx.ephemeral_key_XXX = ax->kx_0; | ||
1433 | msg->kx.private_key_XXX = *my_private_key; | ||
1434 | msg->r_ephemeral_key_XXX = ax->last_ephemeral; | ||
1435 | #endif | ||
1436 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1437 | "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n", | ||
1438 | GCT_2s (t), | ||
1439 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
1440 | GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel)); | ||
1441 | |||
1442 | /* Compute authenticator (this is the main difference to #send_kx()) */ | ||
1443 | GNUNET_CRYPTO_hash (&ax->RK, | ||
1444 | sizeof(ax->RK), | ||
1445 | &msg->auth); | ||
1446 | /* Compute when to be triggered again; actual job will | ||
1447 | be scheduled via #connection_ready_cb() */ | ||
1448 | t->kx_retry_delay | ||
1449 | = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | ||
1450 | t->next_kx_attempt | ||
1451 | = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | ||
1452 | |||
1453 | /* Send via cc, mark it as unready */ | ||
1454 | mark_connection_unready (ct); | ||
1455 | |||
1456 | /* Update state machine, unless we are already OK */ | ||
1457 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1458 | GCT_change_estate (t, | ||
1459 | CADET_TUNNEL_KEY_AX_AUTH_SENT); | ||
1460 | GCC_transmit (cc, | ||
1461 | env); | ||
1462 | GNUNET_STATISTICS_update (stats, | ||
1463 | "# KX_AUTH transmitted", | ||
1464 | 1, | ||
1465 | GNUNET_NO); | ||
1466 | } | ||
1467 | |||
1468 | |||
1469 | /** | ||
1470 | * Cleanup state used by @a ax. | ||
1471 | * | ||
1472 | * @param ax state to free, but not memory of @a ax itself | ||
1473 | */ | ||
1474 | static void | ||
1475 | cleanup_ax (struct CadetTunnelAxolotl *ax) | ||
1476 | { | ||
1477 | while (NULL != ax->skipped_head) | ||
1478 | delete_skipped_key (ax, | ||
1479 | ax->skipped_head); | ||
1480 | GNUNET_assert (0 == ax->skipped); | ||
1481 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0); | ||
1482 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs); | ||
1483 | } | ||
1484 | |||
1485 | |||
1486 | /** | ||
1487 | * Update our Axolotl key state based on the KX data we received. | ||
1488 | * Computes the new chain keys, and root keys, etc, and also checks | ||
1489 | * whether this is a replay of the current chain. | ||
1490 | * | ||
1491 | * @param[in,out] ax chain key state to recompute | ||
1492 | * @param pid peer identity of the other peer | ||
1493 | * @param ephemeral_key ephemeral public key of the other peer | ||
1494 | * @param ratchet_key senders next ephemeral public key | ||
1495 | * @return #GNUNET_OK on success, #GNUNET_NO if the resulting | ||
1496 | * root key is already in @a ax and thus the KX is useless; | ||
1497 | * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id) | ||
1498 | */ | ||
1499 | static int | ||
1500 | update_ax_by_kx (struct CadetTunnelAxolotl *ax, | ||
1501 | const struct GNUNET_PeerIdentity *pid, | ||
1502 | const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key, | ||
1503 | const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key) | ||
1504 | { | ||
1505 | struct GNUNET_HashCode key_material[3]; | ||
1506 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; | ||
1507 | const char salt[] = "CADET Axolotl salt"; | ||
1508 | int am_I_alice; | ||
1509 | |||
1510 | if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid))) | ||
1511 | { | ||
1512 | GNUNET_break_op (0); | ||
1513 | return GNUNET_SYSERR; | ||
1514 | } | ||
1515 | if (0 == GNUNET_memcmp (&ax->DHRr, | ||
1516 | ratchet_key)) | ||
1517 | { | ||
1518 | GNUNET_STATISTICS_update (stats, | ||
1519 | "# Ratchet key already known", | ||
1520 | 1, | ||
1521 | GNUNET_NO); | ||
1522 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1523 | "Ratchet key already known. Ignoring KX.\n"); | ||
1524 | return GNUNET_NO; | ||
1525 | } | ||
1526 | |||
1527 | ax->DHRr = *ratchet_key; | ||
1528 | ax->last_ephemeral = *ephemeral_key; | ||
1529 | /* ECDH A B0 */ | ||
1530 | if (GNUNET_YES == am_I_alice) | ||
1531 | { | ||
1532 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */ | ||
1533 | ephemeral_key, /* B0 */ | ||
1534 | &key_material[0]); | ||
1535 | } | ||
1536 | else | ||
1537 | { | ||
1538 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */ | ||
1539 | &pid->public_key, /* A */ | ||
1540 | &key_material[0]); | ||
1541 | } | ||
1542 | /* ECDH A0 B */ | ||
1543 | if (GNUNET_YES == am_I_alice) | ||
1544 | { | ||
1545 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */ | ||
1546 | &pid->public_key, /* B */ | ||
1547 | &key_material[1]); | ||
1548 | } | ||
1549 | else | ||
1550 | { | ||
1551 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */ | ||
1552 | ephemeral_key, /* A0 */ | ||
1553 | &key_material[1]); | ||
1554 | } | ||
1555 | |||
1556 | /* ECDH A0 B0 */ | ||
1557 | GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */ | ||
1558 | ephemeral_key, /* B0 or A0 */ | ||
1559 | &key_material[2]); | ||
1560 | /* KDF */ | ||
1561 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
1562 | salt, sizeof(salt), | ||
1563 | &key_material, sizeof(key_material), | ||
1564 | NULL); | ||
1565 | |||
1566 | if (0 == memcmp (&ax->RK, | ||
1567 | &keys[0], | ||
1568 | sizeof(ax->RK))) | ||
1569 | { | ||
1570 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1571 | "Root key already known. Ignoring KX.\n"); | ||
1572 | GNUNET_STATISTICS_update (stats, | ||
1573 | "# Root key already known", | ||
1574 | 1, | ||
1575 | GNUNET_NO); | ||
1576 | return GNUNET_NO; | ||
1577 | } | ||
1578 | |||
1579 | ax->RK = keys[0]; | ||
1580 | if (GNUNET_YES == am_I_alice) | ||
1581 | { | ||
1582 | ax->HKr = keys[1]; | ||
1583 | ax->NHKs = keys[2]; | ||
1584 | ax->NHKr = keys[3]; | ||
1585 | ax->CKr = keys[4]; | ||
1586 | ax->ratchet_flag = GNUNET_YES; | ||
1587 | } | ||
1588 | else | ||
1589 | { | ||
1590 | ax->HKs = keys[1]; | ||
1591 | ax->NHKr = keys[2]; | ||
1592 | ax->NHKs = keys[3]; | ||
1593 | ax->CKs = keys[4]; | ||
1594 | ax->ratchet_flag = GNUNET_NO; | ||
1595 | ax->ratchet_expiration | ||
1596 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
1597 | ratchet_time); | ||
1598 | } | ||
1599 | return GNUNET_OK; | ||
1600 | } | ||
1601 | |||
1602 | |||
1603 | /** | ||
1604 | * Try to redo the KX or KX_AUTH handshake, if we can. | ||
1605 | * | ||
1606 | * @param cls the `struct CadetTunnel` to do KX for. | ||
1607 | */ | ||
1608 | static void | ||
1609 | retry_kx (void *cls) | ||
1610 | { | ||
1611 | struct CadetTunnel *t = cls; | ||
1612 | struct CadetTunnelAxolotl *ax; | ||
1613 | |||
1614 | t->kx_task = NULL; | ||
1615 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1616 | "Trying to make KX progress on %s in state %s\n", | ||
1617 | GCT_2s (t), | ||
1618 | estate2s (t->estate)); | ||
1619 | switch (t->estate) | ||
1620 | { | ||
1621 | case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */ | ||
1622 | case CADET_TUNNEL_KEY_AX_SENT: /* trying again */ | ||
1623 | send_kx (t, | ||
1624 | NULL, | ||
1625 | &t->ax); | ||
1626 | break; | ||
1627 | |||
1628 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1629 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1630 | /* We are responding, so only require reply | ||
1631 | if WE have a channel waiting. */ | ||
1632 | if (NULL != t->unverified_ax) | ||
1633 | { | ||
1634 | /* Send AX_AUTH so we might get this one verified */ | ||
1635 | ax = t->unverified_ax; | ||
1636 | } | ||
1637 | else | ||
1638 | { | ||
1639 | /* How can this be? */ | ||
1640 | GNUNET_break (0); | ||
1641 | ax = &t->ax; | ||
1642 | } | ||
1643 | send_kx_auth (t, | ||
1644 | NULL, | ||
1645 | ax, | ||
1646 | (0 == GCT_count_channels (t)) | ||
1647 | ? GNUNET_NO | ||
1648 | : GNUNET_YES); | ||
1649 | break; | ||
1650 | |||
1651 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1652 | /* We are responding, so only require reply | ||
1653 | if WE have a channel waiting. */ | ||
1654 | if (NULL != t->unverified_ax) | ||
1655 | { | ||
1656 | /* Send AX_AUTH so we might get this one verified */ | ||
1657 | ax = t->unverified_ax; | ||
1658 | } | ||
1659 | else | ||
1660 | { | ||
1661 | /* How can this be? */ | ||
1662 | GNUNET_break (0); | ||
1663 | ax = &t->ax; | ||
1664 | } | ||
1665 | send_kx_auth (t, | ||
1666 | NULL, | ||
1667 | ax, | ||
1668 | (0 == GCT_count_channels (t)) | ||
1669 | ? GNUNET_NO | ||
1670 | : GNUNET_YES); | ||
1671 | break; | ||
1672 | |||
1673 | case CADET_TUNNEL_KEY_OK: | ||
1674 | /* Must have been the *other* peer asking us to | ||
1675 | respond with a KX_AUTH. */ | ||
1676 | if (NULL != t->unverified_ax) | ||
1677 | { | ||
1678 | /* Sending AX_AUTH in response to AX so we might get this one verified */ | ||
1679 | ax = t->unverified_ax; | ||
1680 | } | ||
1681 | else | ||
1682 | { | ||
1683 | /* Sending AX_AUTH in response to AX_AUTH */ | ||
1684 | ax = &t->ax; | ||
1685 | } | ||
1686 | send_kx_auth (t, | ||
1687 | NULL, | ||
1688 | ax, | ||
1689 | GNUNET_NO); | ||
1690 | break; | ||
1691 | } | ||
1692 | } | ||
1693 | |||
1694 | |||
1695 | void | ||
1696 | GCT_handle_kx (struct CadetTConnection *ct, | ||
1697 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1698 | { | ||
1699 | struct CadetTunnel *t = ct->t; | ||
1700 | int ret; | ||
1701 | |||
1702 | GNUNET_STATISTICS_update (stats, | ||
1703 | "# KX received", | ||
1704 | 1, | ||
1705 | GNUNET_NO); | ||
1706 | if (GNUNET_YES == | ||
1707 | GCT_alice_or_betty (GCP_get_id (t->destination))) | ||
1708 | { | ||
1709 | /* Betty/Bob is not allowed to send KX! */ | ||
1710 | GNUNET_break_op (0); | ||
1711 | return; | ||
1712 | } | ||
1713 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1714 | "Received KX message from %s with ephemeral %s from %s on connection %s\n", | ||
1715 | GCT_2s (t), | ||
1716 | GNUNET_e2s (&msg->ephemeral_key), | ||
1717 | GNUNET_i2s (GCP_get_id (t->destination)), | ||
1718 | GCC_2s (ct->cc)); | ||
1719 | #if 1 | ||
1720 | if ((0 == | ||
1721 | memcmp (&t->ax.DHRr, | ||
1722 | &msg->ratchet_key, | ||
1723 | sizeof(msg->ratchet_key))) && | ||
1724 | (0 == | ||
1725 | memcmp (&t->ax.last_ephemeral, | ||
1726 | &msg->ephemeral_key, | ||
1727 | sizeof(msg->ephemeral_key)))) | ||
1728 | |||
1729 | { | ||
1730 | GNUNET_STATISTICS_update (stats, | ||
1731 | "# Duplicate KX received", | ||
1732 | 1, | ||
1733 | GNUNET_NO); | ||
1734 | send_kx_auth (t, | ||
1735 | ct, | ||
1736 | &t->ax, | ||
1737 | GNUNET_NO); | ||
1738 | return; | ||
1739 | } | ||
1740 | #endif | ||
1741 | /* We only keep ONE unverified KX around, so if there is an existing one, | ||
1742 | clean it up. */ | ||
1743 | if (NULL != t->unverified_ax) | ||
1744 | { | ||
1745 | if ((0 == | ||
1746 | memcmp (&t->unverified_ax->DHRr, | ||
1747 | &msg->ratchet_key, | ||
1748 | sizeof(msg->ratchet_key))) && | ||
1749 | (0 == | ||
1750 | memcmp (&t->unverified_ax->last_ephemeral, | ||
1751 | &msg->ephemeral_key, | ||
1752 | sizeof(msg->ephemeral_key)))) | ||
1753 | { | ||
1754 | GNUNET_STATISTICS_update (stats, | ||
1755 | "# Duplicate unverified KX received", | ||
1756 | 1, | ||
1757 | GNUNET_NO); | ||
1758 | #if 1 | ||
1759 | send_kx_auth (t, | ||
1760 | ct, | ||
1761 | t->unverified_ax, | ||
1762 | GNUNET_NO); | ||
1763 | return; | ||
1764 | #endif | ||
1765 | } | ||
1766 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1767 | "Dropping old unverified KX state.\n"); | ||
1768 | GNUNET_STATISTICS_update (stats, | ||
1769 | "# Unverified KX dropped for fresh KX", | ||
1770 | 1, | ||
1771 | GNUNET_NO); | ||
1772 | GNUNET_break (NULL == t->unverified_ax->skipped_head); | ||
1773 | memset (t->unverified_ax, | ||
1774 | 0, | ||
1775 | sizeof(struct CadetTunnelAxolotl)); | ||
1776 | } | ||
1777 | else | ||
1778 | { | ||
1779 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1780 | "Creating fresh unverified KX for %s\n", | ||
1781 | GCT_2s (t)); | ||
1782 | GNUNET_STATISTICS_update (stats, | ||
1783 | "# Fresh KX setup", | ||
1784 | 1, | ||
1785 | GNUNET_NO); | ||
1786 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); | ||
1787 | } | ||
1788 | /* Set as the 'current' RK/DHRr the one we are currently using, | ||
1789 | so that the duplicate-detection logic of | ||
1790 | #update_ax_by_kx can work. */ | ||
1791 | t->unverified_ax->RK = t->ax.RK; | ||
1792 | t->unverified_ax->DHRr = t->ax.DHRr; | ||
1793 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1794 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1795 | t->unverified_attempts = 0; | ||
1796 | |||
1797 | /* Update 'ax' by the new key material */ | ||
1798 | ret = update_ax_by_kx (t->unverified_ax, | ||
1799 | GCP_get_id (t->destination), | ||
1800 | &msg->ephemeral_key, | ||
1801 | &msg->ratchet_key); | ||
1802 | GNUNET_break (GNUNET_SYSERR != ret); | ||
1803 | if (GNUNET_OK != ret) | ||
1804 | { | ||
1805 | GNUNET_STATISTICS_update (stats, | ||
1806 | "# Useless KX", | ||
1807 | 1, | ||
1808 | GNUNET_NO); | ||
1809 | return; /* duplicate KX, nothing to do */ | ||
1810 | } | ||
1811 | /* move ahead in our state machine */ | ||
1812 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
1813 | GCT_change_estate (t, | ||
1814 | CADET_TUNNEL_KEY_AX_RECV); | ||
1815 | else if (CADET_TUNNEL_KEY_AX_SENT == t->estate) | ||
1816 | GCT_change_estate (t, | ||
1817 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | ||
1818 | |||
1819 | /* KX is still not done, try again our end. */ | ||
1820 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1821 | { | ||
1822 | if (NULL != t->kx_task) | ||
1823 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1824 | t->kx_task | ||
1825 | = GNUNET_SCHEDULER_add_now (&retry_kx, | ||
1826 | t); | ||
1827 | } | ||
1828 | } | ||
1829 | |||
1830 | |||
1831 | #if DEBUG_KX | ||
1832 | static void | ||
1833 | check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1834 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2) | ||
1835 | { | ||
1836 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1837 | struct GNUNET_CRYPTO_EcdhePublicKey p2; | ||
1838 | struct GNUNET_HashCode hc1; | ||
1839 | struct GNUNET_HashCode hc2; | ||
1840 | |||
1841 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1842 | &p1); | ||
1843 | GNUNET_CRYPTO_ecdhe_key_get_public (e2, | ||
1844 | &p2); | ||
1845 | GNUNET_assert (GNUNET_OK == | ||
1846 | GNUNET_CRYPTO_ecc_ecdh (e1, | ||
1847 | &p2, | ||
1848 | &hc1)); | ||
1849 | GNUNET_assert (GNUNET_OK == | ||
1850 | GNUNET_CRYPTO_ecc_ecdh (e2, | ||
1851 | &p1, | ||
1852 | &hc2)); | ||
1853 | GNUNET_break (0 == GNUNET_memcmp (&hc1, | ||
1854 | &hc2)); | ||
1855 | } | ||
1856 | |||
1857 | |||
1858 | static void | ||
1859 | check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1860 | const struct GNUNET_CRYPTO_EddsaPrivateKey *e2) | ||
1861 | { | ||
1862 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1863 | struct GNUNET_CRYPTO_EddsaPublicKey p2; | ||
1864 | struct GNUNET_HashCode hc1; | ||
1865 | struct GNUNET_HashCode hc2; | ||
1866 | |||
1867 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1868 | &p1); | ||
1869 | GNUNET_CRYPTO_eddsa_key_get_public (e2, | ||
1870 | &p2); | ||
1871 | GNUNET_assert (GNUNET_OK == | ||
1872 | GNUNET_CRYPTO_ecdh_eddsa (e1, | ||
1873 | &p2, | ||
1874 | &hc1)); | ||
1875 | GNUNET_assert (GNUNET_OK == | ||
1876 | GNUNET_CRYPTO_eddsa_ecdh (e2, | ||
1877 | &p1, | ||
1878 | &hc2)); | ||
1879 | GNUNET_break (0 == GNUNET_memcmp (&hc1, | ||
1880 | &hc2)); | ||
1881 | } | ||
1882 | |||
1883 | |||
1884 | static void | ||
1885 | test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1886 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2, | ||
1887 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d1, | ||
1888 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d2) | ||
1889 | { | ||
1890 | check_ee (e1, e2); | ||
1891 | check_ed (e1, d2); | ||
1892 | check_ed (e2, d1); | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | #endif | ||
1897 | |||
1898 | |||
1899 | /** | ||
1900 | * Handle KX_AUTH message. | ||
1901 | * | ||
1902 | * @param ct connection/tunnel combo that received encrypted message | ||
1903 | * @param msg the key exchange message | ||
1904 | */ | ||
1905 | void | ||
1906 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
1907 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1908 | { | ||
1909 | struct CadetTunnel *t = ct->t; | ||
1910 | struct CadetTunnelAxolotl ax_tmp; | ||
1911 | struct GNUNET_HashCode kx_auth; | ||
1912 | int ret; | ||
1913 | |||
1914 | GNUNET_STATISTICS_update (stats, | ||
1915 | "# KX_AUTH received", | ||
1916 | 1, | ||
1917 | GNUNET_NO); | ||
1918 | if ((CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | ||
1919 | (CADET_TUNNEL_KEY_AX_RECV == t->estate)) | ||
1920 | { | ||
1921 | /* Confusing, we got a KX_AUTH before we even send our own | ||
1922 | KX. This should not happen. We'll send our own KX ASAP anyway, | ||
1923 | so let's ignore this here. */ | ||
1924 | GNUNET_break_op (0); | ||
1925 | return; | ||
1926 | } | ||
1927 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1928 | "Handling KX_AUTH message from %s with ephemeral %s\n", | ||
1929 | GCT_2s (t), | ||
1930 | GNUNET_e2s (&msg->kx.ephemeral_key)); | ||
1931 | /* We do everything in ax_tmp until we've checked the authentication | ||
1932 | so we don't clobber anything we care about by accident. */ | ||
1933 | ax_tmp = t->ax; | ||
1934 | |||
1935 | /* Update 'ax' by the new key material */ | ||
1936 | ret = update_ax_by_kx (&ax_tmp, | ||
1937 | GCP_get_id (t->destination), | ||
1938 | &msg->kx.ephemeral_key, | ||
1939 | &msg->kx.ratchet_key); | ||
1940 | if (GNUNET_OK != ret) | ||
1941 | { | ||
1942 | if (GNUNET_NO == ret) | ||
1943 | GNUNET_STATISTICS_update (stats, | ||
1944 | "# redundant KX_AUTH received", | ||
1945 | 1, | ||
1946 | GNUNET_NO); | ||
1947 | else | ||
1948 | GNUNET_break (0); /* connect to self!? */ | ||
1949 | return; | ||
1950 | } | ||
1951 | GNUNET_CRYPTO_hash (&ax_tmp.RK, | ||
1952 | sizeof(ax_tmp.RK), | ||
1953 | &kx_auth); | ||
1954 | if (0 != GNUNET_memcmp (&kx_auth, | ||
1955 | &msg->auth)) | ||
1956 | { | ||
1957 | /* This KX_AUTH is not using the latest KX/KX_AUTH data | ||
1958 | we transmitted to the sender, refuse it, try KX again. */ | ||
1959 | GNUNET_STATISTICS_update (stats, | ||
1960 | "# KX_AUTH not using our last KX received (auth failure)", | ||
1961 | 1, | ||
1962 | GNUNET_NO); | ||
1963 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1964 | "KX AUTH mismatch!\n"); | ||
1965 | #if DEBUG_KX | ||
1966 | { | ||
1967 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
1968 | |||
1969 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0, | ||
1970 | &ephemeral_key); | ||
1971 | if (0 != GNUNET_memcmp (&ephemeral_key, | ||
1972 | &msg->r_ephemeral_key_XXX)) | ||
1973 | { | ||
1974 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1975 | "My ephemeral is %s!\n", | ||
1976 | GNUNET_e2s (&ephemeral_key)); | ||
1977 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1978 | "Response is for ephemeral %s!\n", | ||
1979 | GNUNET_e2s (&msg->r_ephemeral_key_XXX)); | ||
1980 | } | ||
1981 | else | ||
1982 | { | ||
1983 | test_crypto_bug (&ax_tmp.kx_0, | ||
1984 | &msg->kx.ephemeral_key_XXX, | ||
1985 | my_private_key, | ||
1986 | &msg->kx.private_key_XXX); | ||
1987 | } | ||
1988 | } | ||
1989 | #endif | ||
1990 | if (NULL == t->kx_task) | ||
1991 | t->kx_task | ||
1992 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
1993 | &retry_kx, | ||
1994 | t); | ||
1995 | return; | ||
1996 | } | ||
1997 | /* Yep, we're good. */ | ||
1998 | t->ax = ax_tmp; | ||
1999 | if (NULL != t->unverified_ax) | ||
2000 | { | ||
2001 | /* We got some "stale" KX before, drop that. */ | ||
2002 | cleanup_ax (t->unverified_ax); | ||
2003 | GNUNET_free (t->unverified_ax); | ||
2004 | t->unverified_ax = NULL; | ||
2005 | } | ||
2006 | |||
2007 | /* move ahead in our state machine */ | ||
2008 | switch (t->estate) | ||
2009 | { | ||
2010 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2011 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2012 | /* Checked above, this is impossible. */ | ||
2013 | GNUNET_assert (0); | ||
2014 | break; | ||
2015 | |||
2016 | case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */ | ||
2017 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */ | ||
2018 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */ | ||
2019 | GCT_change_estate (t, | ||
2020 | CADET_TUNNEL_KEY_OK); | ||
2021 | break; | ||
2022 | |||
2023 | case CADET_TUNNEL_KEY_OK: | ||
2024 | /* Did not expect another KX_AUTH, but so what, still acceptable. | ||
2025 | Nothing to do here. */ | ||
2026 | break; | ||
2027 | } | ||
2028 | if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags))) | ||
2029 | { | ||
2030 | send_kx_auth (t, | ||
2031 | NULL, | ||
2032 | &t->ax, | ||
2033 | GNUNET_NO); | ||
2034 | } | ||
2035 | } | ||
2036 | |||
2037 | |||
2038 | /* ************************************** end core crypto ***************************** */ | ||
2039 | |||
2040 | |||
2041 | /** | ||
2042 | * Compute the next free channel tunnel number for this tunnel. | ||
2043 | * | ||
2044 | * @param t the tunnel | ||
2045 | * @return unused number that can uniquely identify a channel in the tunnel | ||
2046 | */ | ||
2047 | static struct GNUNET_CADET_ChannelTunnelNumber | ||
2048 | get_next_free_ctn (struct CadetTunnel *t) | ||
2049 | { | ||
2050 | #define HIGH_BIT 0x8000000 | ||
2051 | struct GNUNET_CADET_ChannelTunnelNumber ret; | ||
2052 | uint32_t ctn; | ||
2053 | int cmp; | ||
2054 | uint32_t highbit; | ||
2055 | |||
2056 | cmp = GNUNET_memcmp (&my_full_id, | ||
2057 | GCP_get_id (GCT_get_destination (t))); | ||
2058 | if (0 < cmp) | ||
2059 | highbit = HIGH_BIT; | ||
2060 | else if (0 > cmp) | ||
2061 | highbit = 0; | ||
2062 | else | ||
2063 | GNUNET_assert (0); // loopback must never go here! | ||
2064 | ctn = ntohl (t->next_ctn.cn); | ||
2065 | while (NULL != | ||
2066 | GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
2067 | ctn | highbit)) | ||
2068 | { | ||
2069 | ctn = ((ctn + 1) & (~HIGH_BIT)); | ||
2070 | } | ||
2071 | t->next_ctn.cn = htonl ((ctn + 1) & (~HIGH_BIT)); | ||
2072 | ret.cn = htonl (ctn | highbit); | ||
2073 | return ret; | ||
2074 | } | ||
2075 | |||
2076 | |||
2077 | /** | ||
2078 | * Add a channel to a tunnel, and notify channel that we are ready | ||
2079 | * for transmission if we are already up. Otherwise that notification | ||
2080 | * will be done later in #notify_tunnel_up_cb(). | ||
2081 | * | ||
2082 | * @param t Tunnel. | ||
2083 | * @param ch Channel | ||
2084 | * @return unique number identifying @a ch within @a t | ||
2085 | */ | ||
2086 | struct GNUNET_CADET_ChannelTunnelNumber | ||
2087 | GCT_add_channel (struct CadetTunnel *t, | ||
2088 | struct CadetChannel *ch) | ||
2089 | { | ||
2090 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
2091 | |||
2092 | ctn = get_next_free_ctn (t); | ||
2093 | if (NULL != t->destroy_task) | ||
2094 | { | ||
2095 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2096 | t->destroy_task = NULL; | ||
2097 | } | ||
2098 | GNUNET_assert (GNUNET_YES == | ||
2099 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | ||
2100 | ntohl (ctn.cn), | ||
2101 | ch, | ||
2102 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2103 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2104 | "Adding %s to %s with state %d\n", | ||
2105 | GCCH_2s (ch), | ||
2106 | GCT_2s (t), | ||
2107 | t->estate); | ||
2108 | switch (t->estate) | ||
2109 | { | ||
2110 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2111 | /* waiting for connection to start KX */ | ||
2112 | break; | ||
2113 | |||
2114 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2115 | case CADET_TUNNEL_KEY_AX_SENT: | ||
2116 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
2117 | /* we're currently waiting for KX to complete */ | ||
2118 | break; | ||
2119 | |||
2120 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
2121 | /* waiting for OTHER peer to send us data, | ||
2122 | we might need to prompt more aggressively! */ | ||
2123 | if (NULL == t->kx_task) | ||
2124 | t->kx_task | ||
2125 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2126 | &retry_kx, | ||
2127 | t); | ||
2128 | break; | ||
2129 | |||
2130 | case CADET_TUNNEL_KEY_OK: | ||
2131 | /* We are ready. Tell the new channel that we are up. */ | ||
2132 | GCCH_tunnel_up (ch); | ||
2133 | break; | ||
2134 | } | ||
2135 | return ctn; | ||
2136 | } | ||
2137 | |||
2138 | |||
2139 | /** | ||
2140 | * We lost a connection, remove it from our list and clean up | ||
2141 | * the connection object itself. | ||
2142 | * | ||
2143 | * @param ct binding of connection to tunnel of the connection that was lost. | ||
2144 | */ | ||
2145 | void | ||
2146 | GCT_connection_lost (struct CadetTConnection *ct) | ||
2147 | { | ||
2148 | struct CadetTunnel *t = ct->t; | ||
2149 | |||
2150 | if (GNUNET_YES == ct->is_ready) | ||
2151 | { | ||
2152 | GNUNET_CONTAINER_DLL_remove (t->connection_ready_head, | ||
2153 | t->connection_ready_tail, | ||
2154 | ct); | ||
2155 | t->num_ready_connections--; | ||
2156 | } | ||
2157 | else | ||
2158 | { | ||
2159 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
2160 | t->connection_busy_tail, | ||
2161 | ct); | ||
2162 | t->num_busy_connections--; | ||
2163 | } | ||
2164 | GNUNET_free (ct); | ||
2165 | } | ||
2166 | |||
2167 | |||
2168 | /** | ||
2169 | * Clean up connection @a ct of a tunnel. | ||
2170 | * | ||
2171 | * @param cls the `struct CadetTunnel` | ||
2172 | * @param ct connection to clean up | ||
2173 | */ | ||
2174 | static void | ||
2175 | destroy_t_connection (void *cls, | ||
2176 | struct CadetTConnection *ct) | ||
2177 | { | ||
2178 | struct CadetTunnel *t = cls; | ||
2179 | struct CadetConnection *cc = ct->cc; | ||
2180 | |||
2181 | GNUNET_assert (ct->t == t); | ||
2182 | GCT_connection_lost (ct); | ||
2183 | GCC_destroy_without_tunnel (cc); | ||
2184 | } | ||
2185 | |||
2186 | |||
2187 | /** | ||
2188 | * This tunnel is no longer used, destroy it. | ||
2189 | * | ||
2190 | * @param cls the idle tunnel | ||
2191 | */ | ||
2192 | static void | ||
2193 | destroy_tunnel (void *cls) | ||
2194 | { | ||
2195 | struct CadetTunnel *t = cls; | ||
2196 | struct CadetTunnelQueueEntry *tq; | ||
2197 | |||
2198 | t->destroy_task = NULL; | ||
2199 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2200 | "Destroying idle %s\n", | ||
2201 | GCT_2s (t)); | ||
2202 | GNUNET_assert (0 == GCT_count_channels (t)); | ||
2203 | GCT_iterate_connections (t, | ||
2204 | &destroy_t_connection, | ||
2205 | t); | ||
2206 | GNUNET_assert (NULL == t->connection_ready_head); | ||
2207 | GNUNET_assert (NULL == t->connection_busy_head); | ||
2208 | while (NULL != (tq = t->tq_head)) | ||
2209 | { | ||
2210 | if (NULL != tq->cont) | ||
2211 | tq->cont (tq->cont_cls, | ||
2212 | NULL); | ||
2213 | GCT_send_cancel (tq); | ||
2214 | } | ||
2215 | GCP_drop_tunnel (t->destination, | ||
2216 | t); | ||
2217 | GNUNET_CONTAINER_multihashmap32_destroy (t->channels); | ||
2218 | if (NULL != t->maintain_connections_task) | ||
2219 | { | ||
2220 | GNUNET_SCHEDULER_cancel (t->maintain_connections_task); | ||
2221 | t->maintain_connections_task = NULL; | ||
2222 | } | ||
2223 | if (NULL != t->send_task) | ||
2224 | { | ||
2225 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
2226 | t->send_task = NULL; | ||
2227 | } | ||
2228 | if (NULL != t->kx_task) | ||
2229 | { | ||
2230 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2231 | t->kx_task = NULL; | ||
2232 | } | ||
2233 | GNUNET_MST_destroy (t->mst); | ||
2234 | GNUNET_MQ_destroy (t->mq); | ||
2235 | if (NULL != t->unverified_ax) | ||
2236 | { | ||
2237 | cleanup_ax (t->unverified_ax); | ||
2238 | GNUNET_free (t->unverified_ax); | ||
2239 | } | ||
2240 | cleanup_ax (&t->ax); | ||
2241 | GNUNET_assert (NULL == t->destroy_task); | ||
2242 | GNUNET_free (t); | ||
2243 | } | ||
2244 | |||
2245 | |||
2246 | /** | ||
2247 | * Remove a channel from a tunnel. | ||
2248 | * | ||
2249 | * @param t Tunnel. | ||
2250 | * @param ch Channel | ||
2251 | * @param ctn unique number identifying @a ch within @a t | ||
2252 | */ | ||
2253 | void | ||
2254 | GCT_remove_channel (struct CadetTunnel *t, | ||
2255 | struct CadetChannel *ch, | ||
2256 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
2257 | { | ||
2258 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2259 | "Removing %s from %s\n", | ||
2260 | GCCH_2s (ch), | ||
2261 | GCT_2s (t)); | ||
2262 | GNUNET_assert (GNUNET_YES == | ||
2263 | GNUNET_CONTAINER_multihashmap32_remove (t->channels, | ||
2264 | ntohl (ctn.cn), | ||
2265 | ch)); | ||
2266 | if ((0 == | ||
2267 | GCT_count_channels (t)) && | ||
2268 | (NULL == t->destroy_task)) | ||
2269 | { | ||
2270 | t->destroy_task | ||
2271 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | ||
2272 | &destroy_tunnel, | ||
2273 | t); | ||
2274 | } | ||
2275 | } | ||
2276 | |||
2277 | |||
2278 | /** | ||
2279 | * Destroy remaining channels during shutdown. | ||
2280 | * | ||
2281 | * @param cls the `struct CadetTunnel` of the channel | ||
2282 | * @param key key of the channel | ||
2283 | * @param value the `struct CadetChannel` | ||
2284 | * @return #GNUNET_OK (continue to iterate) | ||
2285 | */ | ||
2286 | static int | ||
2287 | destroy_remaining_channels (void *cls, | ||
2288 | uint32_t key, | ||
2289 | void *value) | ||
2290 | { | ||
2291 | struct CadetChannel *ch = value; | ||
2292 | |||
2293 | GCCH_handle_remote_destroy (ch, | ||
2294 | NULL); | ||
2295 | return GNUNET_OK; | ||
2296 | } | ||
2297 | |||
2298 | |||
2299 | /** | ||
2300 | * Destroys the tunnel @a t now, without delay. Used during shutdown. | ||
2301 | * | ||
2302 | * @param t tunnel to destroy | ||
2303 | */ | ||
2304 | void | ||
2305 | GCT_destroy_tunnel_now (struct CadetTunnel *t) | ||
2306 | { | ||
2307 | GNUNET_assert (GNUNET_YES == shutting_down); | ||
2308 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
2309 | &destroy_remaining_channels, | ||
2310 | t); | ||
2311 | GNUNET_assert (0 == | ||
2312 | GCT_count_channels (t)); | ||
2313 | if (NULL != t->destroy_task) | ||
2314 | { | ||
2315 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2316 | t->destroy_task = NULL; | ||
2317 | } | ||
2318 | destroy_tunnel (t); | ||
2319 | } | ||
2320 | |||
2321 | |||
2322 | /** | ||
2323 | * Send normal payload from queue in @a t via connection @a ct. | ||
2324 | * Does nothing if our payload queue is empty. | ||
2325 | * | ||
2326 | * @param t tunnel to send data from | ||
2327 | * @param ct connection to use for transmission (is ready) | ||
2328 | */ | ||
2329 | static void | ||
2330 | try_send_normal_payload (struct CadetTunnel *t, | ||
2331 | struct CadetTConnection *ct) | ||
2332 | { | ||
2333 | struct CadetTunnelQueueEntry *tq; | ||
2334 | |||
2335 | GNUNET_assert (GNUNET_YES == ct->is_ready); | ||
2336 | tq = t->tq_head; | ||
2337 | if (NULL == tq) | ||
2338 | { | ||
2339 | /* no messages pending right now */ | ||
2340 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2341 | "Not sending payload of %s on ready %s (nothing pending)\n", | ||
2342 | GCT_2s (t), | ||
2343 | GCC_2s (ct->cc)); | ||
2344 | return; | ||
2345 | } | ||
2346 | /* ready to send message 'tq' on tunnel 'ct' */ | ||
2347 | GNUNET_assert (t == tq->t); | ||
2348 | GNUNET_CONTAINER_DLL_remove (t->tq_head, | ||
2349 | t->tq_tail, | ||
2350 | tq); | ||
2351 | if (NULL != tq->cid) | ||
2352 | *tq->cid = *GCC_get_id (ct->cc); | ||
2353 | mark_connection_unready (ct); | ||
2354 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2355 | "Sending payload of %s on %s\n", | ||
2356 | GCT_2s (t), | ||
2357 | GCC_2s (ct->cc)); | ||
2358 | GCC_transmit (ct->cc, | ||
2359 | tq->env); | ||
2360 | if (NULL != tq->cont) | ||
2361 | tq->cont (tq->cont_cls, | ||
2362 | GCC_get_id (ct->cc)); | ||
2363 | GNUNET_free (tq); | ||
2364 | } | ||
2365 | |||
2366 | |||
2367 | /** | ||
2368 | * A connection is @a is_ready for transmission. Looks at our message | ||
2369 | * queue and if there is a message, sends it out via the connection. | ||
2370 | * | ||
2371 | * @param cls the `struct CadetTConnection` that is @a is_ready | ||
2372 | * @param is_ready #GNUNET_YES if connection are now ready, | ||
2373 | * #GNUNET_NO if connection are no longer ready | ||
2374 | */ | ||
2375 | static void | ||
2376 | connection_ready_cb (void *cls, | ||
2377 | int is_ready) | ||
2378 | { | ||
2379 | struct CadetTConnection *ct = cls; | ||
2380 | struct CadetTunnel *t = ct->t; | ||
2381 | |||
2382 | if (GNUNET_NO == is_ready) | ||
2383 | { | ||
2384 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2385 | "%s no longer ready for %s\n", | ||
2386 | GCC_2s (ct->cc), | ||
2387 | GCT_2s (t)); | ||
2388 | mark_connection_unready (ct); | ||
2389 | return; | ||
2390 | } | ||
2391 | GNUNET_assert (GNUNET_NO == ct->is_ready); | ||
2392 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
2393 | t->connection_busy_tail, | ||
2394 | ct); | ||
2395 | GNUNET_assert (0 < t->num_busy_connections); | ||
2396 | t->num_busy_connections--; | ||
2397 | ct->is_ready = GNUNET_YES; | ||
2398 | GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head, | ||
2399 | t->connection_ready_tail, | ||
2400 | ct); | ||
2401 | t->num_ready_connections++; | ||
2402 | |||
2403 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2404 | "%s now ready for %s in state %s\n", | ||
2405 | GCC_2s (ct->cc), | ||
2406 | GCT_2s (t), | ||
2407 | estate2s (t->estate)); | ||
2408 | switch (t->estate) | ||
2409 | { | ||
2410 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2411 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2412 | "Do not begin KX for %s if WE have no channels waiting. Retrying after %llu\n", | ||
2413 | GCT_2s (t), | ||
2414 | (unsigned long long) GNUNET_TIME_absolute_get_remaining ( | ||
2415 | t->next_kx_attempt).rel_value_us); | ||
2416 | /* Do not begin KX if WE have no channels waiting! */ | ||
2417 | if (0 != GNUNET_TIME_absolute_get_remaining ( | ||
2418 | t->next_kx_attempt).rel_value_us) | ||
2419 | return; /* wait for timeout before retrying */ | ||
2420 | /* We are uninitialized, just transmit immediately, | ||
2421 | without undue delay. */ | ||
2422 | |||
2423 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2424 | "Why for %s \n", | ||
2425 | GCT_2s (t)); | ||
2426 | |||
2427 | if (NULL != t->kx_task) | ||
2428 | { | ||
2429 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2430 | t->kx_task = NULL; | ||
2431 | } | ||
2432 | send_kx (t, | ||
2433 | ct, | ||
2434 | &t->ax); | ||
2435 | if ((0 == | ||
2436 | GCT_count_channels (t)) && | ||
2437 | (NULL == t->destroy_task)) | ||
2438 | { | ||
2439 | t->destroy_task | ||
2440 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | ||
2441 | &destroy_tunnel, | ||
2442 | t); | ||
2443 | } | ||
2444 | break; | ||
2445 | |||
2446 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2447 | case CADET_TUNNEL_KEY_AX_SENT: | ||
2448 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
2449 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
2450 | /* we're currently waiting for KX to complete, schedule job */ | ||
2451 | if (NULL == t->kx_task) | ||
2452 | t->kx_task | ||
2453 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2454 | &retry_kx, | ||
2455 | t); | ||
2456 | break; | ||
2457 | |||
2458 | case CADET_TUNNEL_KEY_OK: | ||
2459 | if (GNUNET_YES == t->kx_auth_requested) | ||
2460 | { | ||
2461 | if (0 != GNUNET_TIME_absolute_get_remaining ( | ||
2462 | t->next_kx_attempt).rel_value_us) | ||
2463 | return; /* wait for timeout */ | ||
2464 | if (NULL != t->kx_task) | ||
2465 | { | ||
2466 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2467 | t->kx_task = NULL; | ||
2468 | } | ||
2469 | send_kx_auth (t, | ||
2470 | ct, | ||
2471 | &t->ax, | ||
2472 | GNUNET_NO); | ||
2473 | return; | ||
2474 | } | ||
2475 | try_send_normal_payload (t, | ||
2476 | ct); | ||
2477 | break; | ||
2478 | } | ||
2479 | } | ||
2480 | |||
2481 | |||
2482 | /** | ||
2483 | * Called when either we have a new connection, or a new message in the | ||
2484 | * queue, or some existing connection has transmission capacity. Looks | ||
2485 | * at our message queue and if there is a message, picks a connection | ||
2486 | * to send it on. | ||
2487 | * | ||
2488 | * @param cls the `struct CadetTunnel` to process messages on | ||
2489 | */ | ||
2490 | static void | ||
2491 | trigger_transmissions (void *cls) | ||
2492 | { | ||
2493 | struct CadetTunnel *t = cls; | ||
2494 | struct CadetTConnection *ct; | ||
2495 | |||
2496 | t->send_task = NULL; | ||
2497 | if (NULL == t->tq_head) | ||
2498 | return; /* no messages pending right now */ | ||
2499 | ct = get_ready_connection (t); | ||
2500 | if (NULL == ct) | ||
2501 | return; /* no connections ready */ | ||
2502 | try_send_normal_payload (t, | ||
2503 | ct); | ||
2504 | } | ||
2505 | |||
2506 | |||
2507 | /** | ||
2508 | * Closure for #evaluate_connection. Used to assemble summary information | ||
2509 | * about the existing connections so we can evaluate a new path. | ||
2510 | */ | ||
2511 | struct EvaluationSummary | ||
2512 | { | ||
2513 | /** | ||
2514 | * Minimum length of any of our connections, `UINT_MAX` if we have none. | ||
2515 | */ | ||
2516 | unsigned int min_length; | ||
2517 | |||
2518 | /** | ||
2519 | * Maximum length of any of our connections, 0 if we have none. | ||
2520 | */ | ||
2521 | unsigned int max_length; | ||
2522 | |||
2523 | /** | ||
2524 | * Minimum desirability of any of our connections, UINT64_MAX if we have none. | ||
2525 | */ | ||
2526 | GNUNET_CONTAINER_HeapCostType min_desire; | ||
2527 | |||
2528 | /** | ||
2529 | * Maximum desirability of any of our connections, 0 if we have none. | ||
2530 | */ | ||
2531 | GNUNET_CONTAINER_HeapCostType max_desire; | ||
2532 | |||
2533 | /** | ||
2534 | * Path we are comparing against for #evaluate_connection, can be NULL. | ||
2535 | */ | ||
2536 | struct CadetPeerPath *path; | ||
2537 | |||
2538 | /** | ||
2539 | * Connection deemed the "worst" so far encountered by #evaluate_connection, | ||
2540 | * NULL if we did not yet encounter any connections. | ||
2541 | */ | ||
2542 | struct CadetTConnection *worst; | ||
2543 | |||
2544 | /** | ||
2545 | * Numeric score of @e worst, only set if @e worst is non-NULL. | ||
2546 | */ | ||
2547 | double worst_score; | ||
2548 | |||
2549 | /** | ||
2550 | * Set to #GNUNET_YES if we have a connection over @e path already. | ||
2551 | */ | ||
2552 | int duplicate; | ||
2553 | }; | ||
2554 | |||
2555 | |||
2556 | /** | ||
2557 | * Evaluate a connection, updating our summary information in @a cls about | ||
2558 | * what kinds of connections we have. | ||
2559 | * | ||
2560 | * @param cls the `struct EvaluationSummary *` to update | ||
2561 | * @param ct a connection to include in the summary | ||
2562 | */ | ||
2563 | static void | ||
2564 | evaluate_connection (void *cls, | ||
2565 | struct CadetTConnection *ct) | ||
2566 | { | ||
2567 | struct EvaluationSummary *es = cls; | ||
2568 | struct CadetConnection *cc = ct->cc; | ||
2569 | unsigned int ct_length; | ||
2570 | struct CadetPeerPath *ps; | ||
2571 | const struct CadetConnectionMetrics *metrics; | ||
2572 | GNUNET_CONTAINER_HeapCostType ct_desirability; | ||
2573 | struct GNUNET_TIME_Relative uptime; | ||
2574 | struct GNUNET_TIME_Relative last_use; | ||
2575 | double score; | ||
2576 | double success_rate; | ||
2577 | |||
2578 | ps = GCC_get_path (cc, | ||
2579 | &ct_length); | ||
2580 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2581 | "Evaluating path %s of existing %s\n", | ||
2582 | GCPP_2s (ps), | ||
2583 | GCC_2s (cc)); | ||
2584 | if (ps == es->path) | ||
2585 | { | ||
2586 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2587 | "Ignoring duplicate path %s.\n", | ||
2588 | GCPP_2s (es->path)); | ||
2589 | es->duplicate = GNUNET_YES; | ||
2590 | return; | ||
2591 | } | ||
2592 | if (NULL != es->path) | ||
2593 | { | ||
2594 | int duplicate = GNUNET_YES; | ||
2595 | |||
2596 | for (unsigned int i = 0; i < ct_length; i++) | ||
2597 | { | ||
2598 | GNUNET_assert (GCPP_get_length (es->path) > i); | ||
2599 | if (GCPP_get_peer_at_offset (es->path, | ||
2600 | i) != | ||
2601 | GCPP_get_peer_at_offset (ps, | ||
2602 | i)) | ||
2603 | { | ||
2604 | duplicate = GNUNET_NO; | ||
2605 | break; | ||
2606 | } | ||
2607 | } | ||
2608 | if (GNUNET_YES == duplicate) | ||
2609 | { | ||
2610 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2611 | "Ignoring overlapping path %s.\n", | ||
2612 | GCPP_2s (es->path)); | ||
2613 | es->duplicate = GNUNET_YES; | ||
2614 | return; | ||
2615 | } | ||
2616 | else | ||
2617 | { | ||
2618 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2619 | "Known path %s differs from proposed path\n", | ||
2620 | GCPP_2s (ps)); | ||
2621 | } | ||
2622 | } | ||
2623 | |||
2624 | ct_desirability = GCPP_get_desirability (ps); | ||
2625 | metrics = GCC_get_metrics (cc); | ||
2626 | uptime = GNUNET_TIME_absolute_get_duration (metrics->age); | ||
2627 | last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use); | ||
2628 | /* We add 1.0 here to avoid division by zero. */ | ||
2629 | success_rate = (metrics->num_acked_transmissions + 1.0) | ||
2630 | / (metrics->num_successes + 1.0); | ||
2631 | score | ||
2632 | = ct_desirability | ||
2633 | + 100.0 / (1.0 + ct_length) /* longer paths = better */ | ||
2634 | + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */ | ||
2635 | - last_use.rel_value_us / 1000L; /* longer idle = worse */ | ||
2636 | score *= success_rate; /* weigh overall by success rate */ | ||
2637 | |||
2638 | if ((NULL == es->worst) || | ||
2639 | (score < es->worst_score)) | ||
2640 | { | ||
2641 | es->worst = ct; | ||
2642 | es->worst_score = score; | ||
2643 | } | ||
2644 | es->min_length = GNUNET_MIN (es->min_length, | ||
2645 | ct_length); | ||
2646 | es->max_length = GNUNET_MAX (es->max_length, | ||
2647 | ct_length); | ||
2648 | es->min_desire = GNUNET_MIN (es->min_desire, | ||
2649 | ct_desirability); | ||
2650 | es->max_desire = GNUNET_MAX (es->max_desire, | ||
2651 | ct_desirability); | ||
2652 | } | ||
2653 | |||
2654 | |||
2655 | /** | ||
2656 | * Consider using the path @a p for the tunnel @a t. | ||
2657 | * The tunnel destination is at offset @a off in path @a p. | ||
2658 | * | ||
2659 | * @param cls our tunnel | ||
2660 | * @param path a path to our destination | ||
2661 | * @param off offset of the destination on path @a path | ||
2662 | * @return #GNUNET_YES (should keep iterating) | ||
2663 | */ | ||
2664 | static int | ||
2665 | consider_path_cb (void *cls, | ||
2666 | struct CadetPeerPath *path, | ||
2667 | unsigned int off) | ||
2668 | { | ||
2669 | struct CadetTunnel *t = cls; | ||
2670 | struct EvaluationSummary es; | ||
2671 | struct CadetTConnection *ct; | ||
2672 | |||
2673 | GNUNET_assert (off < GCPP_get_length (path)); | ||
2674 | GNUNET_assert (GCPP_get_peer_at_offset (path, | ||
2675 | off) == t->destination); | ||
2676 | es.min_length = UINT_MAX; | ||
2677 | es.max_length = 0; | ||
2678 | es.max_desire = 0; | ||
2679 | es.min_desire = UINT64_MAX; | ||
2680 | es.path = path; | ||
2681 | es.duplicate = GNUNET_NO; | ||
2682 | es.worst = NULL; | ||
2683 | |||
2684 | /* Compute evaluation summary over existing connections. */ | ||
2685 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2686 | "Evaluating proposed path %s for target %s\n", | ||
2687 | GCPP_2s (path), | ||
2688 | GCT_2s (t)); | ||
2689 | /* FIXME: suspect this does not ACTUALLY iterate | ||
2690 | over all existing paths, otherwise dup detection | ||
2691 | should work!!! */ | ||
2692 | GCT_iterate_connections (t, | ||
2693 | &evaluate_connection, | ||
2694 | &es); | ||
2695 | if (GNUNET_YES == es.duplicate) | ||
2696 | return GNUNET_YES; | ||
2697 | |||
2698 | /* FIXME: not sure we should really just count | ||
2699 | 'num_connections' here, as they may all have | ||
2700 | consistently failed to connect. */ | ||
2701 | |||
2702 | /* We iterate by increasing path length; if we have enough paths and | ||
2703 | this one is more than twice as long than what we are currently | ||
2704 | using, then ignore all of these super-long ones! */ | ||
2705 | if ((GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
2706 | (es.min_length * 2 < off) && | ||
2707 | (es.max_length < off)) | ||
2708 | { | ||
2709 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2710 | "Ignoring paths of length %u, they are way too long.\n", | ||
2711 | es.min_length * 2); | ||
2712 | return GNUNET_NO; | ||
2713 | } | ||
2714 | /* If we have enough paths and this one looks no better, ignore it. */ | ||
2715 | if ((GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
2716 | (es.min_length < GCPP_get_length (path)) && | ||
2717 | (es.min_desire > GCPP_get_desirability (path)) && | ||
2718 | (es.max_length < off)) | ||
2719 | { | ||
2720 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2721 | "Ignoring path (%u/%llu) to %s, got something better already.\n", | ||
2722 | GCPP_get_length (path), | ||
2723 | (unsigned long long) GCPP_get_desirability (path), | ||
2724 | GCP_2s (t->destination)); | ||
2725 | return GNUNET_YES; | ||
2726 | } | ||
2727 | |||
2728 | /* Path is interesting (better by some metric, or we don't have | ||
2729 | enough paths yet). */ | ||
2730 | ct = GNUNET_new (struct CadetTConnection); | ||
2731 | ct->created = GNUNET_TIME_absolute_get (); | ||
2732 | ct->t = t; | ||
2733 | ct->cc = GCC_create (t->destination, | ||
2734 | path, | ||
2735 | off, | ||
2736 | ct, | ||
2737 | &connection_ready_cb, | ||
2738 | ct); | ||
2739 | |||
2740 | /* FIXME: schedule job to kill connection (and path?) if it takes | ||
2741 | too long to get ready! (And track performance data on how long | ||
2742 | other connections took with the tunnel!) | ||
2743 | => Note: to be done within 'connection'-logic! */ | ||
2744 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, | ||
2745 | t->connection_busy_tail, | ||
2746 | ct); | ||
2747 | t->num_busy_connections++; | ||
2748 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2749 | "Found interesting path %s for %s, created %s\n", | ||
2750 | GCPP_2s (path), | ||
2751 | GCT_2s (t), | ||
2752 | GCC_2s (ct->cc)); | ||
2753 | return GNUNET_YES; | ||
2754 | } | ||
2755 | |||
2756 | |||
2757 | /** | ||
2758 | * Function called to maintain the connections underlying our tunnel. | ||
2759 | * Tries to maintain (incl. tear down) connections for the tunnel, and | ||
2760 | * if there is a significant change, may trigger transmissions. | ||
2761 | * | ||
2762 | * Basically, needs to check if there are connections that perform | ||
2763 | * badly, and if so eventually kill them and trigger a replacement. | ||
2764 | * The strategy is to open one more connection than | ||
2765 | * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the | ||
2766 | * least-performing one, and then inquire for new ones. | ||
2767 | * | ||
2768 | * @param cls the `struct CadetTunnel` | ||
2769 | */ | ||
2770 | static void | ||
2771 | maintain_connections_cb (void *cls) | ||
2772 | { | ||
2773 | struct CadetTunnel *t = cls; | ||
2774 | struct GNUNET_TIME_Relative delay; | ||
2775 | struct EvaluationSummary es; | ||
2776 | |||
2777 | t->maintain_connections_task = NULL; | ||
2778 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2779 | "Performing connection maintenance for %s.\n", | ||
2780 | GCT_2s (t)); | ||
2781 | |||
2782 | es.min_length = UINT_MAX; | ||
2783 | es.max_length = 0; | ||
2784 | es.max_desire = 0; | ||
2785 | es.min_desire = UINT64_MAX; | ||
2786 | es.path = NULL; | ||
2787 | es.worst = NULL; | ||
2788 | es.duplicate = GNUNET_NO; | ||
2789 | GCT_iterate_connections (t, | ||
2790 | &evaluate_connection, | ||
2791 | &es); | ||
2792 | if ((NULL != es.worst) && | ||
2793 | (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL)) | ||
2794 | { | ||
2795 | /* Clear out worst-performing connection 'es.worst'. */ | ||
2796 | destroy_t_connection (t, | ||
2797 | es.worst); | ||
2798 | } | ||
2799 | |||
2800 | /* Consider additional paths */ | ||
2801 | (void) GCP_iterate_paths (t->destination, | ||
2802 | &consider_path_cb, | ||
2803 | t); | ||
2804 | |||
2805 | /* FIXME: calculate when to try again based on how well we are doing; | ||
2806 | in particular, if we have to few connections, we might be able | ||
2807 | to do without this (as PATHS should tell us whenever a new path | ||
2808 | is available instantly; however, need to make sure this job is | ||
2809 | restarted after that happens). | ||
2810 | Furthermore, if the paths we do know are in a reasonably narrow | ||
2811 | quality band and are plentyful, we might also consider us stabilized | ||
2812 | and then reduce the frequency accordingly. */delay = GNUNET_TIME_UNIT_MINUTES; | ||
2813 | t->maintain_connections_task | ||
2814 | = GNUNET_SCHEDULER_add_delayed (delay, | ||
2815 | &maintain_connections_cb, | ||
2816 | t); | ||
2817 | } | ||
2818 | |||
2819 | |||
2820 | void | ||
2821 | GCT_consider_path (struct CadetTunnel *t, | ||
2822 | struct CadetPeerPath *p, | ||
2823 | unsigned int off) | ||
2824 | { | ||
2825 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2826 | "Considering %s for %s (offset %u)\n", | ||
2827 | GCPP_2s (p), | ||
2828 | GCT_2s (t), | ||
2829 | off); | ||
2830 | (void) consider_path_cb (t, | ||
2831 | p, | ||
2832 | off); | ||
2833 | } | ||
2834 | |||
2835 | |||
2836 | /** | ||
2837 | * We got a keepalive. Track in statistics. | ||
2838 | * | ||
2839 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2840 | * @param msg the message we received on the tunnel | ||
2841 | */ | ||
2842 | static void | ||
2843 | handle_plaintext_keepalive (void *cls, | ||
2844 | const struct GNUNET_MessageHeader *msg) | ||
2845 | { | ||
2846 | struct CadetTunnel *t = cls; | ||
2847 | |||
2848 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2849 | "Received KEEPALIVE on %s\n", | ||
2850 | GCT_2s (t)); | ||
2851 | GNUNET_STATISTICS_update (stats, | ||
2852 | "# keepalives received", | ||
2853 | 1, | ||
2854 | GNUNET_NO); | ||
2855 | } | ||
2856 | |||
2857 | |||
2858 | /** | ||
2859 | * Check that @a msg is well-formed. | ||
2860 | * | ||
2861 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2862 | * @param msg the message we received on the tunnel | ||
2863 | * @return #GNUNET_OK (any variable-size payload goes) | ||
2864 | */ | ||
2865 | static int | ||
2866 | check_plaintext_data (void *cls, | ||
2867 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
2868 | { | ||
2869 | return GNUNET_OK; | ||
2870 | } | ||
2871 | |||
2872 | |||
2873 | /** | ||
2874 | * We received payload data for a channel. Locate the channel | ||
2875 | * and process the data, or return an error if the channel is unknown. | ||
2876 | * | ||
2877 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2878 | * @param msg the message we received on the tunnel | ||
2879 | */ | ||
2880 | static void | ||
2881 | handle_plaintext_data (void *cls, | ||
2882 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
2883 | { | ||
2884 | struct CadetTunnel *t = cls; | ||
2885 | struct CadetChannel *ch; | ||
2886 | |||
2887 | ch = lookup_channel (t, | ||
2888 | msg->ctn); | ||
2889 | if (NULL == ch) | ||
2890 | { | ||
2891 | /* We don't know about such a channel, might have been destroyed on our | ||
2892 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
2893 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2894 | "Received %u bytes of application data for unknown channel %u, sending DESTROY\n", | ||
2895 | (unsigned int) (ntohs (msg->header.size) - sizeof(*msg)), | ||
2896 | ntohl (msg->ctn.cn)); | ||
2897 | GCT_send_channel_destroy (t, | ||
2898 | msg->ctn); | ||
2899 | return; | ||
2900 | } | ||
2901 | GCCH_handle_channel_plaintext_data (ch, | ||
2902 | GCC_get_id (t->current_ct->cc), | ||
2903 | msg); | ||
2904 | } | ||
2905 | |||
2906 | |||
2907 | /** | ||
2908 | * We received an acknowledgement for data we sent on a channel. | ||
2909 | * Locate the channel and process it, or return an error if the | ||
2910 | * channel is unknown. | ||
2911 | * | ||
2912 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2913 | * @param ack the message we received on the tunnel | ||
2914 | */ | ||
2915 | static void | ||
2916 | handle_plaintext_data_ack (void *cls, | ||
2917 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
2918 | { | ||
2919 | struct CadetTunnel *t = cls; | ||
2920 | struct CadetChannel *ch; | ||
2921 | |||
2922 | ch = lookup_channel (t, | ||
2923 | ack->ctn); | ||
2924 | if (NULL == ch) | ||
2925 | { | ||
2926 | /* We don't know about such a channel, might have been destroyed on our | ||
2927 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
2928 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2929 | "Received DATA_ACK for unknown channel %u, sending DESTROY\n", | ||
2930 | ntohl (ack->ctn.cn)); | ||
2931 | GCT_send_channel_destroy (t, | ||
2932 | ack->ctn); | ||
2933 | return; | ||
2934 | } | ||
2935 | GCCH_handle_channel_plaintext_data_ack (ch, | ||
2936 | GCC_get_id (t->current_ct->cc), | ||
2937 | ack); | ||
2938 | } | ||
2939 | |||
2940 | |||
2941 | /** | ||
2942 | * We have received a request to open a channel to a port from | ||
2943 | * another peer. Creates the incoming channel. | ||
2944 | * | ||
2945 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2946 | * @param copen the message we received on the tunnel | ||
2947 | */ | ||
2948 | static void | ||
2949 | handle_plaintext_channel_open (void *cls, | ||
2950 | const struct | ||
2951 | GNUNET_CADET_ChannelOpenMessage *copen) | ||
2952 | { | ||
2953 | struct CadetTunnel *t = cls; | ||
2954 | struct CadetChannel *ch; | ||
2955 | |||
2956 | ch = GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
2957 | ntohl (copen->ctn.cn)); | ||
2958 | if (NULL != ch) | ||
2959 | { | ||
2960 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2961 | "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n", | ||
2962 | GNUNET_h2s (&copen->h_port), | ||
2963 | GCT_2s (t), | ||
2964 | GCCH_2s (ch)); | ||
2965 | GCCH_handle_duplicate_open (ch, | ||
2966 | GCC_get_id (t->current_ct->cc)); | ||
2967 | return; | ||
2968 | } | ||
2969 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2970 | "Received CHANNEL_OPEN on h_port %s from %s\n", | ||
2971 | GNUNET_h2s (&copen->h_port), | ||
2972 | GCT_2s (t)); | ||
2973 | ch = GCCH_channel_incoming_new (t, | ||
2974 | copen->ctn, | ||
2975 | &copen->h_port, | ||
2976 | ntohl (copen->opt)); | ||
2977 | if (NULL != t->destroy_task) | ||
2978 | { | ||
2979 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2980 | t->destroy_task = NULL; | ||
2981 | } | ||
2982 | GNUNET_assert (GNUNET_OK == | ||
2983 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | ||
2984 | ntohl (copen->ctn.cn), | ||
2985 | ch, | ||
2986 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2987 | } | ||
2988 | |||
2989 | |||
2990 | /** | ||
2991 | * Send a DESTROY message via the tunnel. | ||
2992 | * | ||
2993 | * @param t the tunnel to transmit over | ||
2994 | * @param ctn ID of the channel to destroy | ||
2995 | */ | ||
2996 | void | ||
2997 | GCT_send_channel_destroy (struct CadetTunnel *t, | ||
2998 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
2999 | { | ||
3000 | struct GNUNET_CADET_ChannelDestroyMessage msg; | ||
3001 | |||
3002 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3003 | "Sending DESTROY message for channel ID %u\n", | ||
3004 | ntohl (ctn.cn)); | ||
3005 | msg.header.size = htons (sizeof(msg)); | ||
3006 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
3007 | msg.reserved = htonl (0); | ||
3008 | msg.ctn = ctn; | ||
3009 | GCT_send (t, | ||
3010 | &msg.header, | ||
3011 | NULL, | ||
3012 | NULL, | ||
3013 | &ctn); | ||
3014 | } | ||
3015 | |||
3016 | |||
3017 | /** | ||
3018 | * We have received confirmation from the target peer that the | ||
3019 | * given channel could be established (the port is open). | ||
3020 | * Tell the client. | ||
3021 | * | ||
3022 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
3023 | * @param cm the message we received on the tunnel | ||
3024 | */ | ||
3025 | static void | ||
3026 | handle_plaintext_channel_open_ack (void *cls, | ||
3027 | const struct | ||
3028 | GNUNET_CADET_ChannelOpenAckMessage *cm) | ||
3029 | { | ||
3030 | struct CadetTunnel *t = cls; | ||
3031 | struct CadetChannel *ch; | ||
3032 | |||
3033 | ch = lookup_channel (t, | ||
3034 | cm->ctn); | ||
3035 | if (NULL == ch) | ||
3036 | { | ||
3037 | /* We don't know about such a channel, might have been destroyed on our | ||
3038 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
3039 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3040 | "Received channel OPEN_ACK for unknown channel %u, sending DESTROY\n", | ||
3041 | ntohl (cm->ctn.cn)); | ||
3042 | GCT_send_channel_destroy (t, | ||
3043 | cm->ctn); | ||
3044 | return; | ||
3045 | } | ||
3046 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3047 | "Received channel OPEN_ACK on channel %s from %s\n", | ||
3048 | GCCH_2s (ch), | ||
3049 | GCT_2s (t)); | ||
3050 | GCCH_handle_channel_open_ack (ch, | ||
3051 | GCC_get_id (t->current_ct->cc), | ||
3052 | &cm->port); | ||
3053 | } | ||
3054 | |||
3055 | |||
3056 | /** | ||
3057 | * We received a message saying that a channel should be destroyed. | ||
3058 | * Pass it on to the correct channel. | ||
3059 | * | ||
3060 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
3061 | * @param cm the message we received on the tunnel | ||
3062 | */ | ||
3063 | static void | ||
3064 | handle_plaintext_channel_destroy (void *cls, | ||
3065 | const struct | ||
3066 | GNUNET_CADET_ChannelDestroyMessage *cm) | ||
3067 | { | ||
3068 | struct CadetTunnel *t = cls; | ||
3069 | struct CadetChannel *ch; | ||
3070 | |||
3071 | ch = lookup_channel (t, | ||
3072 | cm->ctn); | ||
3073 | if (NULL == ch) | ||
3074 | { | ||
3075 | /* We don't know about such a channel, might have been destroyed on our | ||
3076 | end in the meantime, or never existed. */ | ||
3077 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3078 | "Received channel DESTROY for unknown channel %u. Ignoring.\n", | ||
3079 | ntohl (cm->ctn.cn)); | ||
3080 | return; | ||
3081 | } | ||
3082 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3083 | "Received channel DESTROY on %s from %s\n", | ||
3084 | GCCH_2s (ch), | ||
3085 | GCT_2s (t)); | ||
3086 | GCCH_handle_remote_destroy (ch, | ||
3087 | GCC_get_id (t->current_ct->cc)); | ||
3088 | } | ||
3089 | |||
3090 | |||
3091 | /** | ||
3092 | * Handles a message we decrypted, by injecting it into | ||
3093 | * our message queue (which will do the dispatching). | ||
3094 | * | ||
3095 | * @param cls the `struct CadetTunnel` that got the message | ||
3096 | * @param msg the message | ||
3097 | * @return #GNUNET_OK on success (always) | ||
3098 | * #GNUNET_NO to stop further processing (no error) | ||
3099 | * #GNUNET_SYSERR to stop further processing with error | ||
3100 | */ | ||
3101 | static int | ||
3102 | handle_decrypted (void *cls, | ||
3103 | const struct GNUNET_MessageHeader *msg) | ||
3104 | { | ||
3105 | struct CadetTunnel *t = cls; | ||
3106 | |||
3107 | GNUNET_assert (NULL != t->current_ct); | ||
3108 | GNUNET_MQ_inject_message (t->mq, | ||
3109 | msg); | ||
3110 | return GNUNET_OK; | ||
3111 | } | ||
3112 | |||
3113 | |||
3114 | /** | ||
3115 | * Function called if we had an error processing | ||
3116 | * an incoming decrypted message. | ||
3117 | * | ||
3118 | * @param cls the `struct CadetTunnel` | ||
3119 | * @param error error code | ||
3120 | */ | ||
3121 | static void | ||
3122 | decrypted_error_cb (void *cls, | ||
3123 | enum GNUNET_MQ_Error error) | ||
3124 | { | ||
3125 | GNUNET_break_op (0); | ||
3126 | } | ||
3127 | |||
3128 | |||
3129 | /** | ||
3130 | * Create a tunnel to @a destination. Must only be called | ||
3131 | * from within #GCP_get_tunnel(). | ||
3132 | * | ||
3133 | * @param destination where to create the tunnel to | ||
3134 | * @return new tunnel to @a destination | ||
3135 | */ | ||
3136 | struct CadetTunnel * | ||
3137 | GCT_create_tunnel (struct CadetPeer *destination) | ||
3138 | { | ||
3139 | struct CadetTunnel *t = GNUNET_new (struct CadetTunnel); | ||
3140 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
3141 | GNUNET_MQ_hd_fixed_size (plaintext_keepalive, | ||
3142 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE, | ||
3143 | struct GNUNET_MessageHeader, | ||
3144 | t), | ||
3145 | GNUNET_MQ_hd_var_size (plaintext_data, | ||
3146 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA, | ||
3147 | struct GNUNET_CADET_ChannelAppDataMessage, | ||
3148 | t), | ||
3149 | GNUNET_MQ_hd_fixed_size (plaintext_data_ack, | ||
3150 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK, | ||
3151 | struct GNUNET_CADET_ChannelDataAckMessage, | ||
3152 | t), | ||
3153 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open, | ||
3154 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN, | ||
3155 | struct GNUNET_CADET_ChannelOpenMessage, | ||
3156 | t), | ||
3157 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack, | ||
3158 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, | ||
3159 | struct GNUNET_CADET_ChannelOpenAckMessage, | ||
3160 | t), | ||
3161 | GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy, | ||
3162 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, | ||
3163 | struct GNUNET_CADET_ChannelDestroyMessage, | ||
3164 | t), | ||
3165 | GNUNET_MQ_handler_end () | ||
3166 | }; | ||
3167 | |||
3168 | t->kx_retry_delay = INITIAL_KX_RETRY_DELAY; | ||
3169 | new_ephemeral (&t->ax); | ||
3170 | GNUNET_CRYPTO_ecdhe_key_create (&t->ax.kx_0); | ||
3171 | t->destination = destination; | ||
3172 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); | ||
3173 | t->maintain_connections_task | ||
3174 | = GNUNET_SCHEDULER_add_now (&maintain_connections_cb, | ||
3175 | t); | ||
3176 | t->mq = GNUNET_MQ_queue_for_callbacks (NULL, | ||
3177 | NULL, | ||
3178 | NULL, | ||
3179 | NULL, | ||
3180 | handlers, | ||
3181 | &decrypted_error_cb, | ||
3182 | t); | ||
3183 | t->mst = GNUNET_MST_create (&handle_decrypted, | ||
3184 | t); | ||
3185 | return t; | ||
3186 | } | ||
3187 | |||
3188 | |||
3189 | int | ||
3190 | GCT_add_inbound_connection (struct CadetTunnel *t, | ||
3191 | const struct | ||
3192 | GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
3193 | struct CadetPeerPath *path) | ||
3194 | { | ||
3195 | struct CadetTConnection *ct; | ||
3196 | |||
3197 | ct = GNUNET_new (struct CadetTConnection); | ||
3198 | ct->created = GNUNET_TIME_absolute_get (); | ||
3199 | ct->t = t; | ||
3200 | ct->cc = GCC_create_inbound (t->destination, | ||
3201 | path, | ||
3202 | ct, | ||
3203 | cid, | ||
3204 | &connection_ready_cb, | ||
3205 | ct); | ||
3206 | if (NULL == ct->cc) | ||
3207 | { | ||
3208 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3209 | "%s refused inbound %s (duplicate)\n", | ||
3210 | GCT_2s (t), | ||
3211 | GCC_2s (ct->cc)); | ||
3212 | GNUNET_free (ct); | ||
3213 | return GNUNET_SYSERR; | ||
3214 | } | ||
3215 | /* FIXME: schedule job to kill connection (and path?) if it takes | ||
3216 | too long to get ready! (And track performance data on how long | ||
3217 | other connections took with the tunnel!) | ||
3218 | => Note: to be done within 'connection'-logic! */ | ||
3219 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, | ||
3220 | t->connection_busy_tail, | ||
3221 | ct); | ||
3222 | t->num_busy_connections++; | ||
3223 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3224 | "%s has new %s\n", | ||
3225 | GCT_2s (t), | ||
3226 | GCC_2s (ct->cc)); | ||
3227 | return GNUNET_OK; | ||
3228 | } | ||
3229 | |||
3230 | |||
3231 | /** | ||
3232 | * Handle encrypted message. | ||
3233 | * | ||
3234 | * @param ct connection/tunnel combo that received encrypted message | ||
3235 | * @param msg the encrypted message to decrypt | ||
3236 | */ | ||
3237 | void | ||
3238 | GCT_handle_encrypted (struct CadetTConnection *ct, | ||
3239 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
3240 | { | ||
3241 | struct CadetTunnel *t = ct->t; | ||
3242 | uint16_t size = ntohs (msg->header.size); | ||
3243 | char cbuf[size] GNUNET_ALIGN; | ||
3244 | ssize_t decrypted_size; | ||
3245 | |||
3246 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3247 | "%s received %u bytes of encrypted data in state %d\n", | ||
3248 | GCT_2s (t), | ||
3249 | (unsigned int) size, | ||
3250 | t->estate); | ||
3251 | |||
3252 | switch (t->estate) | ||
3253 | { | ||
3254 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
3255 | case CADET_TUNNEL_KEY_AX_RECV: | ||
3256 | /* We did not even SEND our KX, how can the other peer | ||
3257 | send us encrypted data? Must have been that we went | ||
3258 | down and the other peer still things we are up. | ||
3259 | Let's send it KX back. */ | ||
3260 | GNUNET_STATISTICS_update (stats, | ||
3261 | "# received encrypted without any KX", | ||
3262 | 1, | ||
3263 | GNUNET_NO); | ||
3264 | if (NULL != t->kx_task) | ||
3265 | { | ||
3266 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3267 | t->kx_task = NULL; | ||
3268 | } | ||
3269 | send_kx (t, | ||
3270 | ct, | ||
3271 | &t->ax); | ||
3272 | return; | ||
3273 | |||
3274 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
3275 | /* We send KX, and other peer send KX to us at the same time. | ||
3276 | Neither KX is AUTH'ed, so let's try KX_AUTH this time. */ | ||
3277 | GNUNET_STATISTICS_update (stats, | ||
3278 | "# received encrypted without KX_AUTH", | ||
3279 | 1, | ||
3280 | GNUNET_NO); | ||
3281 | if (NULL != t->kx_task) | ||
3282 | { | ||
3283 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3284 | t->kx_task = NULL; | ||
3285 | } | ||
3286 | send_kx_auth (t, | ||
3287 | ct, | ||
3288 | &t->ax, | ||
3289 | GNUNET_YES); | ||
3290 | return; | ||
3291 | |||
3292 | case CADET_TUNNEL_KEY_AX_SENT: | ||
3293 | /* We did not get the KX of the other peer, but that | ||
3294 | might have been lost. Send our KX again immediately. */ | ||
3295 | GNUNET_STATISTICS_update (stats, | ||
3296 | "# received encrypted without KX", | ||
3297 | 1, | ||
3298 | GNUNET_NO); | ||
3299 | if (NULL != t->kx_task) | ||
3300 | { | ||
3301 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3302 | t->kx_task = NULL; | ||
3303 | } | ||
3304 | send_kx (t, | ||
3305 | ct, | ||
3306 | &t->ax); | ||
3307 | return; | ||
3308 | |||
3309 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
3310 | /* Great, first payload, we might graduate to OK! */ | ||
3311 | case CADET_TUNNEL_KEY_OK: | ||
3312 | /* We are up and running, all good. */ | ||
3313 | break; | ||
3314 | } | ||
3315 | |||
3316 | decrypted_size = -1; | ||
3317 | if (CADET_TUNNEL_KEY_OK == t->estate) | ||
3318 | { | ||
3319 | /* We have well-established key material available, | ||
3320 | try that. (This is the common case.) */ | ||
3321 | decrypted_size = t_ax_decrypt_and_validate (&t->ax, | ||
3322 | cbuf, | ||
3323 | msg, | ||
3324 | size); | ||
3325 | } | ||
3326 | |||
3327 | if ((-1 == decrypted_size) && | ||
3328 | (NULL != t->unverified_ax)) | ||
3329 | { | ||
3330 | /* We have un-authenticated KX material available. We should try | ||
3331 | this as a back-up option, in case the sender crashed and | ||
3332 | switched keys. */ | ||
3333 | decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax, | ||
3334 | cbuf, | ||
3335 | msg, | ||
3336 | size); | ||
3337 | if (-1 != decrypted_size) | ||
3338 | { | ||
3339 | /* It worked! Treat this as authentication of the AX data! */ | ||
3340 | cleanup_ax (&t->ax); | ||
3341 | t->ax = *t->unverified_ax; | ||
3342 | GNUNET_free (t->unverified_ax); | ||
3343 | t->unverified_ax = NULL; | ||
3344 | } | ||
3345 | if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate) | ||
3346 | { | ||
3347 | /* First time it worked, move tunnel into production! */ | ||
3348 | GCT_change_estate (t, | ||
3349 | CADET_TUNNEL_KEY_OK); | ||
3350 | if (NULL != t->send_task) | ||
3351 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
3352 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
3353 | t); | ||
3354 | } | ||
3355 | } | ||
3356 | if (NULL != t->unverified_ax) | ||
3357 | { | ||
3358 | /* We had unverified KX material that was useless; so increment | ||
3359 | counter and eventually move to ignore it. Note that we even do | ||
3360 | this increment if we successfully decrypted with the old KX | ||
3361 | material and thus didn't even both with the new one. This is | ||
3362 | the ideal case, as a malicious injection of bogus KX data | ||
3363 | basically only causes us to increment a counter a few times. */t->unverified_attempts++; | ||
3364 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3365 | "Failed to decrypt message with unverified KX data %u times\n", | ||
3366 | t->unverified_attempts); | ||
3367 | if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS) | ||
3368 | { | ||
3369 | cleanup_ax (t->unverified_ax); | ||
3370 | GNUNET_free (t->unverified_ax); | ||
3371 | t->unverified_ax = NULL; | ||
3372 | } | ||
3373 | } | ||
3374 | |||
3375 | if (-1 == decrypted_size) | ||
3376 | { | ||
3377 | /* Decryption failed for good, complain. */ | ||
3378 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
3379 | "%s failed to decrypt and validate encrypted data, retrying KX\n", | ||
3380 | GCT_2s (t)); | ||
3381 | GNUNET_STATISTICS_update (stats, | ||
3382 | "# unable to decrypt", | ||
3383 | 1, | ||
3384 | GNUNET_NO); | ||
3385 | if (NULL != t->kx_task) | ||
3386 | { | ||
3387 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3388 | t->kx_task = NULL; | ||
3389 | } | ||
3390 | send_kx (t, | ||
3391 | ct, | ||
3392 | &t->ax); | ||
3393 | return; | ||
3394 | } | ||
3395 | GNUNET_STATISTICS_update (stats, | ||
3396 | "# decrypted bytes", | ||
3397 | decrypted_size, | ||
3398 | GNUNET_NO); | ||
3399 | |||
3400 | /* The MST will ultimately call #handle_decrypted() on each message. */ | ||
3401 | t->current_ct = ct; | ||
3402 | GNUNET_break_op (GNUNET_OK == | ||
3403 | GNUNET_MST_from_buffer (t->mst, | ||
3404 | cbuf, | ||
3405 | decrypted_size, | ||
3406 | GNUNET_YES, | ||
3407 | GNUNET_NO)); | ||
3408 | t->current_ct = NULL; | ||
3409 | } | ||
3410 | |||
3411 | |||
3412 | struct CadetTunnelQueueEntry * | ||
3413 | GCT_send (struct CadetTunnel *t, | ||
3414 | const struct GNUNET_MessageHeader *message, | ||
3415 | GCT_SendContinuation cont, | ||
3416 | void *cont_cls, | ||
3417 | struct GNUNET_CADET_ChannelTunnelNumber *ctn) | ||
3418 | { | ||
3419 | struct CadetTunnelQueueEntry *tq; | ||
3420 | uint16_t payload_size; | ||
3421 | struct GNUNET_MQ_Envelope *env; | ||
3422 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; | ||
3423 | struct CadetChannel *ch; | ||
3424 | |||
3425 | if (NULL != ctn) | ||
3426 | { | ||
3427 | ch = lookup_channel (t, | ||
3428 | *ctn); | ||
3429 | if ((NULL != ch) && GCCH_is_type_to_drop (ch, message)) | ||
3430 | { | ||
3431 | GNUNET_break (0); | ||
3432 | return NULL; | ||
3433 | } | ||
3434 | } | ||
3435 | |||
3436 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
3437 | { | ||
3438 | GNUNET_break (0); | ||
3439 | return NULL; | ||
3440 | } | ||
3441 | payload_size = ntohs (message->size); | ||
3442 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3443 | "Encrypting %u bytes for %s\n", | ||
3444 | (unsigned int) payload_size, | ||
3445 | GCT_2s (t)); | ||
3446 | env = GNUNET_MQ_msg_extra (ax_msg, | ||
3447 | payload_size, | ||
3448 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); | ||
3449 | t_ax_encrypt (&t->ax, | ||
3450 | &ax_msg[1], | ||
3451 | message, | ||
3452 | payload_size); | ||
3453 | GNUNET_STATISTICS_update (stats, | ||
3454 | "# encrypted bytes", | ||
3455 | payload_size, | ||
3456 | GNUNET_NO); | ||
3457 | ax_msg->ax_header.Ns = htonl (t->ax.Ns++); | ||
3458 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); | ||
3459 | /* FIXME: we should do this once, not once per message; | ||
3460 | this is a point multiplication, and DHRs does not | ||
3461 | change all the time. */ | ||
3462 | GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs, | ||
3463 | &ax_msg->ax_header.DHRs); | ||
3464 | t_h_encrypt (&t->ax, | ||
3465 | ax_msg); | ||
3466 | t_hmac (&ax_msg->ax_header, | ||
3467 | sizeof(struct GNUNET_CADET_AxHeader) + payload_size, | ||
3468 | 0, | ||
3469 | &t->ax.HKs, | ||
3470 | &ax_msg->hmac); | ||
3471 | |||
3472 | tq = GNUNET_malloc (sizeof(*tq)); | ||
3473 | tq->t = t; | ||
3474 | tq->env = env; | ||
3475 | tq->cid = &ax_msg->cid; /* will initialize 'ax_msg->cid' once we know the connection */ | ||
3476 | tq->cont = cont; | ||
3477 | tq->cont_cls = cont_cls; | ||
3478 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, | ||
3479 | t->tq_tail, | ||
3480 | tq); | ||
3481 | if (NULL != t->send_task) | ||
3482 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
3483 | t->send_task | ||
3484 | = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
3485 | t); | ||
3486 | return tq; | ||
3487 | } | ||
3488 | |||
3489 | |||
3490 | void | ||
3491 | GCT_send_cancel (struct CadetTunnelQueueEntry *tq) | ||
3492 | { | ||
3493 | struct CadetTunnel *t = tq->t; | ||
3494 | |||
3495 | GNUNET_CONTAINER_DLL_remove (t->tq_head, | ||
3496 | t->tq_tail, | ||
3497 | tq); | ||
3498 | GNUNET_MQ_discard (tq->env); | ||
3499 | GNUNET_free (tq); | ||
3500 | } | ||
3501 | |||
3502 | |||
3503 | /** | ||
3504 | * Iterate over all connections of a tunnel. | ||
3505 | * | ||
3506 | * @param t Tunnel whose connections to iterate. | ||
3507 | * @param iter Iterator. | ||
3508 | * @param iter_cls Closure for @c iter. | ||
3509 | */ | ||
3510 | void | ||
3511 | GCT_iterate_connections (struct CadetTunnel *t, | ||
3512 | GCT_ConnectionIterator iter, | ||
3513 | void *iter_cls) | ||
3514 | { | ||
3515 | struct CadetTConnection *n; | ||
3516 | |||
3517 | for (struct CadetTConnection *ct = t->connection_ready_head; | ||
3518 | NULL != ct; | ||
3519 | ct = n) | ||
3520 | { | ||
3521 | n = ct->next; | ||
3522 | iter (iter_cls, | ||
3523 | ct); | ||
3524 | } | ||
3525 | for (struct CadetTConnection *ct = t->connection_busy_head; | ||
3526 | NULL != ct; | ||
3527 | ct = n) | ||
3528 | { | ||
3529 | n = ct->next; | ||
3530 | iter (iter_cls, | ||
3531 | ct); | ||
3532 | } | ||
3533 | } | ||
3534 | |||
3535 | |||
3536 | /** | ||
3537 | * Closure for #iterate_channels_cb. | ||
3538 | */ | ||
3539 | struct ChanIterCls | ||
3540 | { | ||
3541 | /** | ||
3542 | * Function to call. | ||
3543 | */ | ||
3544 | GCT_ChannelIterator iter; | ||
3545 | |||
3546 | /** | ||
3547 | * Closure for @e iter. | ||
3548 | */ | ||
3549 | void *iter_cls; | ||
3550 | }; | ||
3551 | |||
3552 | |||
3553 | /** | ||
3554 | * Helper function for #GCT_iterate_channels. | ||
3555 | * | ||
3556 | * @param cls the `struct ChanIterCls` | ||
3557 | * @param key unused | ||
3558 | * @param value a `struct CadetChannel` | ||
3559 | * @return #GNUNET_OK | ||
3560 | */ | ||
3561 | static int | ||
3562 | iterate_channels_cb (void *cls, | ||
3563 | uint32_t key, | ||
3564 | void *value) | ||
3565 | { | ||
3566 | struct ChanIterCls *ctx = cls; | ||
3567 | struct CadetChannel *ch = value; | ||
3568 | |||
3569 | ctx->iter (ctx->iter_cls, | ||
3570 | ch); | ||
3571 | return GNUNET_OK; | ||
3572 | } | ||
3573 | |||
3574 | |||
3575 | /** | ||
3576 | * Iterate over all channels of a tunnel. | ||
3577 | * | ||
3578 | * @param t Tunnel whose channels to iterate. | ||
3579 | * @param iter Iterator. | ||
3580 | * @param iter_cls Closure for @c iter. | ||
3581 | */ | ||
3582 | void | ||
3583 | GCT_iterate_channels (struct CadetTunnel *t, | ||
3584 | GCT_ChannelIterator iter, | ||
3585 | void *iter_cls) | ||
3586 | { | ||
3587 | struct ChanIterCls ctx; | ||
3588 | |||
3589 | ctx.iter = iter; | ||
3590 | ctx.iter_cls = iter_cls; | ||
3591 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
3592 | &iterate_channels_cb, | ||
3593 | &ctx); | ||
3594 | } | ||
3595 | |||
3596 | |||
3597 | /** | ||
3598 | * Call #GCCH_debug() on a channel. | ||
3599 | * | ||
3600 | * @param cls points to the log level to use | ||
3601 | * @param key unused | ||
3602 | * @param value the `struct CadetChannel` to dump | ||
3603 | * @return #GNUNET_OK (continue iteration) | ||
3604 | */ | ||
3605 | static int | ||
3606 | debug_channel (void *cls, | ||
3607 | uint32_t key, | ||
3608 | void *value) | ||
3609 | { | ||
3610 | const enum GNUNET_ErrorType *level = cls; | ||
3611 | struct CadetChannel *ch = value; | ||
3612 | |||
3613 | GCCH_debug (ch, *level); | ||
3614 | return GNUNET_OK; | ||
3615 | } | ||
3616 | |||
3617 | |||
3618 | #define LOG2(level, ...) GNUNET_log_from_nocheck (level, "cadet-tun", \ | ||
3619 | __VA_ARGS__) | ||
3620 | |||
3621 | |||
3622 | /** | ||
3623 | * Log all possible info about the tunnel state. | ||
3624 | * | ||
3625 | * @param t Tunnel to debug. | ||
3626 | * @param level Debug level to use. | ||
3627 | */ | ||
3628 | void | ||
3629 | GCT_debug (const struct CadetTunnel *t, | ||
3630 | enum GNUNET_ErrorType level) | ||
3631 | { | ||
3632 | #if ! defined(GNUNET_CULL_LOGGING) | ||
3633 | struct CadetTConnection *iter_c; | ||
3634 | int do_log; | ||
3635 | |||
3636 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
3637 | "cadet-tun", | ||
3638 | __FILE__, __FUNCTION__, __LINE__); | ||
3639 | if (0 == do_log) | ||
3640 | return; | ||
3641 | |||
3642 | LOG2 (level, | ||
3643 | "TTT TUNNEL TOWARDS %s in estate %s tq_len: %u #cons: %u\n", | ||
3644 | GCT_2s (t), | ||
3645 | estate2s (t->estate), | ||
3646 | t->tq_len, | ||
3647 | GCT_count_any_connections (t)); | ||
3648 | LOG2 (level, | ||
3649 | "TTT channels:\n"); | ||
3650 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
3651 | &debug_channel, | ||
3652 | &level); | ||
3653 | LOG2 (level, | ||
3654 | "TTT connections:\n"); | ||
3655 | for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next) | ||
3656 | GCC_debug (iter_c->cc, | ||
3657 | level); | ||
3658 | for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next) | ||
3659 | GCC_debug (iter_c->cc, | ||
3660 | level); | ||
3661 | |||
3662 | LOG2 (level, | ||
3663 | "TTT TUNNEL END\n"); | ||
3664 | #endif | ||
3665 | } | ||
3666 | |||
3667 | |||
3668 | /* end of gnunet-service-cadet_tunnels.c */ | ||
diff --git a/src/service/cadet/gnunet-service-cadet_tunnels.h b/src/service/cadet/gnunet-service-cadet_tunnels.h new file mode 100644 index 000000000..e893955a0 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_tunnels.h | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_tunnels.h | ||
23 | * @brief Information we track per tunnel. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_TUNNELS_H | ||
28 | #define GNUNET_SERVICE_CADET_TUNNELS_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * How many connections would we like to have per tunnel? | ||
36 | */ | ||
37 | #define DESIRED_CONNECTIONS_PER_TUNNEL 3 | ||
38 | |||
39 | |||
40 | /** | ||
41 | * All the encryption states a tunnel can be in. | ||
42 | */ | ||
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 t our tunnel | ||
164 | * @param p 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 | * Returns the number of channels using a tunnel. | ||
256 | * | ||
257 | * @param t Tunnel in question. | ||
258 | * @return Number of channels using the tunnel. | ||
259 | */ | ||
260 | unsigned int | ||
261 | GCT_count_channels (struct CadetTunnel *t); | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Counts the number of connections created for a tunnel, | ||
266 | * including busy connections. | ||
267 | * | ||
268 | * @param t Tunnel to be counted. | ||
269 | * @return Number of connections created for the tunnel. | ||
270 | */ | ||
271 | unsigned int | ||
272 | GCT_count_any_connections (const struct CadetTunnel *t); | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Iterator over connections. | ||
277 | * | ||
278 | * @param cls closure | ||
279 | * @param ct one of the connections | ||
280 | */ | ||
281 | typedef void | ||
282 | (*GCT_ConnectionIterator) (void *cls, | ||
283 | struct CadetTConnection *ct); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Iterate over all connections of a tunnel. | ||
288 | * | ||
289 | * @param t Tunnel whose connections to iterate. | ||
290 | * @param iter Iterator. | ||
291 | * @param iter_cls Closure for @c iter. | ||
292 | */ | ||
293 | void | ||
294 | GCT_iterate_connections (struct CadetTunnel *t, | ||
295 | GCT_ConnectionIterator iter, | ||
296 | void *iter_cls); | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Iterator over channels. | ||
301 | * | ||
302 | * @param cls closure | ||
303 | * @param ch one of the channels | ||
304 | */ | ||
305 | typedef void | ||
306 | (*GCT_ChannelIterator) (void *cls, | ||
307 | struct CadetChannel *ch); | ||
308 | |||
309 | |||
310 | /** | ||
311 | * Iterate over all channels of a tunnel. | ||
312 | * | ||
313 | * @param t Tunnel whose channels to iterate. | ||
314 | * @param iter Iterator. | ||
315 | * @param iter_cls Closure for @c iter. | ||
316 | */ | ||
317 | void | ||
318 | GCT_iterate_channels (struct CadetTunnel *t, | ||
319 | GCT_ChannelIterator iter, | ||
320 | void *iter_cls); | ||
321 | |||
322 | |||
323 | /** | ||
324 | * Get the encryption state of a tunnel. | ||
325 | * | ||
326 | * @param t Tunnel. | ||
327 | * | ||
328 | * @return Tunnel's encryption state. | ||
329 | */ | ||
330 | enum CadetTunnelEState | ||
331 | GCT_get_estate (struct CadetTunnel *t); | ||
332 | |||
333 | /** | ||
334 | * Change the tunnel encryption state. | ||
335 | * If the encryption state changes to OK, stop the rekey task. | ||
336 | * | ||
337 | * @param t Tunnel whose encryption state to change, or NULL. | ||
338 | * @param state New encryption state. | ||
339 | */ | ||
340 | void | ||
341 | GCT_change_estate (struct CadetTunnel *t, | ||
342 | enum CadetTunnelEState state); | ||
343 | |||
344 | /** | ||
345 | * Handle KX message that lacks authentication (and which will thus | ||
346 | * only be considered authenticated after we respond with our own | ||
347 | * KX_AUTH and finally successfully decrypt the payload). | ||
348 | * | ||
349 | * @param ct connection/tunnel combo that received encrypted message | ||
350 | * @param msg the key exchange message | ||
351 | */ | ||
352 | void | ||
353 | GCT_handle_kx (struct CadetTConnection *ct, | ||
354 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Handle KX_AUTH message. | ||
359 | * | ||
360 | * @param ct connection/tunnel combo that received encrypted message | ||
361 | * @param msg the key exchange message | ||
362 | */ | ||
363 | void | ||
364 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
365 | const struct | ||
366 | GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Handle encrypted message. | ||
371 | * | ||
372 | * @param ct connection/tunnel combo that received encrypted message | ||
373 | * @param msg the encrypted message to decrypt | ||
374 | */ | ||
375 | void | ||
376 | GCT_handle_encrypted (struct CadetTConnection *ct, | ||
377 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
378 | |||
379 | |||
380 | /** | ||
381 | * Log all possible info about the tunnel state. | ||
382 | * | ||
383 | * @param t Tunnel to debug. | ||
384 | * @param level Debug level to use. | ||
385 | */ | ||
386 | void | ||
387 | GCT_debug (const struct CadetTunnel *t, | ||
388 | enum GNUNET_ErrorType level); | ||
389 | |||
390 | |||
391 | #endif | ||
diff --git a/src/service/cadet/loopcheck.sh b/src/service/cadet/loopcheck.sh new file mode 100755 index 000000000..9b867e95b --- /dev/null +++ b/src/service/cadet/loopcheck.sh | |||
@@ -0,0 +1,57 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | # This script is in the public domain | ||
3 | # POSIX shell solution for named pipes and pipestatus, | ||
4 | # http://shell.cfajohnson.com/cus-faq-2.html#Q11 | ||
5 | # run() { | ||
6 | # j=1 | ||
7 | # while eval "\${pipestatus_$j+:} false"; do | ||
8 | # unset pipestatus_$j | ||
9 | # j=$(($j+1)) | ||
10 | # done | ||
11 | # j=1 com= k=1 l= | ||
12 | # for a; do | ||
13 | # if [ "x$a" = 'x|' ]; then | ||
14 | # com="$com { $l "'3>&- | ||
15 | # echo "pipestatus_'$j'=$?" >&3 | ||
16 | # } 4>&- |' | ||
17 | # j=$(($j+1)) l= | ||
18 | # else | ||
19 | # l="$l \"\$$k\"" | ||
20 | # fi | ||
21 | # k=$(($k+1)) | ||
22 | # done | ||
23 | # com="$com $l"' 3>&- >&4 4>&- | ||
24 | # echo "pipestatus_'$j'=$?"' | ||
25 | # exec 4>&1 | ||
26 | # eval "$(exec 3>&1; eval "$com")" | ||
27 | # exec 4>&- | ||
28 | # j=1 | ||
29 | # while eval "\${pipestatus_$j+:} false"; do | ||
30 | # eval "[ \$pipestatus_$j -eq 0 ]" || return 1 | ||
31 | # j=$(($j+1)) | ||
32 | # done | ||
33 | # return 0 | ||
34 | # } | ||
35 | |||
36 | # # https://mywiki.wooledge.org/Bashism has another solution: | ||
37 | # # mkfifo fifo; command2 <fifo & command1 >fifo; echo "$?" | ||
38 | |||
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/service/cadet/meson.build b/src/service/cadet/meson.build new file mode 100644 index 000000000..0f465e0e2 --- /dev/null +++ b/src/service/cadet/meson.build | |||
@@ -0,0 +1,72 @@ | |||
1 | libgnunetcadet_src = ['cadet_api.c', | ||
2 | 'cadet_api_drop_message.c', | ||
3 | 'cadet_api_get_channel.c', | ||
4 | 'cadet_api_get_path.c', | ||
5 | 'cadet_api_list_peers.c', | ||
6 | 'cadet_api_list_tunnels.c', | ||
7 | 'cadet_api_helper.c'] | ||
8 | |||
9 | gnunetcadet_src = ['gnunet-cadet.c'] | ||
10 | gnunetservicecadet_src = ['gnunet-service-cadet.c', | ||
11 | 'gnunet-service-cadet_channel.c', | ||
12 | 'gnunet-service-cadet_connection.c', | ||
13 | 'gnunet-service-cadet_core.c', | ||
14 | 'gnunet-service-cadet_dht.c', | ||
15 | 'gnunet-service-cadet_hello.c', | ||
16 | 'gnunet-service-cadet_tunnels.c', | ||
17 | 'gnunet-service-cadet_paths.c', | ||
18 | 'gnunet-service-cadet_peer.c'] | ||
19 | |||
20 | configure_file(input : 'cadet.conf.in', | ||
21 | output : 'cadet.conf', | ||
22 | configuration : cdata, | ||
23 | install: true, | ||
24 | install_dir: pkgcfgdir) | ||
25 | |||
26 | if get_option('monolith') | ||
27 | foreach p : libgnunetcadet_src + gnunetservicecadet_src | ||
28 | gnunet_src += 'cadet/' + p | ||
29 | endforeach | ||
30 | endif | ||
31 | |||
32 | libgnunetcadet = library('gnunetcadet', | ||
33 | libgnunetcadet_src, | ||
34 | dependencies: libgnunetutil_dep, | ||
35 | include_directories: [incdir, configuration_inc], | ||
36 | install: true, | ||
37 | soversion: '7', | ||
38 | version: '7.0.0', | ||
39 | install_dir: get_option('libdir')) | ||
40 | libgnunetcadet_dep = declare_dependency(link_with : libgnunetcadet) | ||
41 | pkg.generate(libgnunetcadet, url: 'https://www.gnunet.org', | ||
42 | description : 'API for multicast and multi-hop routing between GNUnet peers') | ||
43 | |||
44 | executable ('gnunet-service-cadet', | ||
45 | gnunetservicecadet_src, | ||
46 | dependencies: [libgnunetcadet_dep, | ||
47 | libgnunetutil_dep, | ||
48 | m_dep, | ||
49 | libgnunetcore_dep, | ||
50 | libgnunetdht_dep, | ||
51 | libgnunetstatistics_dep, | ||
52 | libgnunettransportapplication_dep, | ||
53 | libgnunetpeerstore_dep, | ||
54 | libgnunethello_dep, | ||
55 | libgnunetblock_dep], | ||
56 | include_directories: [incdir, configuration_inc], | ||
57 | install: true, | ||
58 | install_dir: get_option('libdir') / 'gnunet' / 'libexec') | ||
59 | |||
60 | testcadetlocalmq = executable ('test_cadet_local_mq', | ||
61 | ['test_cadet_local_mq.c'], | ||
62 | dependencies: [libgnunetcadet_dep, | ||
63 | libgnunettesting_dep, | ||
64 | libgnunetutil_dep], | ||
65 | include_directories: [incdir, configuration_inc], | ||
66 | install: false) | ||
67 | configure_file(input : 'test_cadet.conf', | ||
68 | output : 'test_cadet.conf', | ||
69 | configuration : cdata, | ||
70 | install: false) | ||
71 | test('test_cadet_local_mq', testcadetlocalmq, workdir: meson.current_build_dir(), suite: 'cadet') | ||
72 | |||
diff --git a/src/service/cadet/profiler.conf b/src/service/cadet/profiler.conf new file mode 100644 index 000000000..7ce283870 --- /dev/null +++ b/src/service/cadet/profiler.conf | |||
@@ -0,0 +1,19 @@ | |||
1 | @INLINE@ test_cadet.conf | ||
2 | |||
3 | [testbed] | ||
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/service/cadet/run_profiler.sh b/src/service/cadet/run_profiler.sh new file mode 100755 index 000000000..4273dcd27 --- /dev/null +++ b/src/service/cadet/run_profiler.sh | |||
@@ -0,0 +1,25 @@ | |||
1 | #!/bin/sh | ||
2 | |||
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/service/cadet/small.dat b/src/service/cadet/small.dat new file mode 100644 index 000000000..c3805ee80 --- /dev/null +++ b/src/service/cadet/small.dat | |||
@@ -0,0 +1,21 @@ | |||
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/service/cadet/test_cadet.conf b/src/service/cadet/test_cadet.conf new file mode 100644 index 000000000..79c86bb59 --- /dev/null +++ b/src/service/cadet/test_cadet.conf | |||
@@ -0,0 +1,109 @@ | |||
1 | [testbed] | ||
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/service/cadet/test_cadet_local_mq.c b/src/service/cadet/test_cadet_local_mq.c new file mode 100644 index 000000000..6f75dfd1f --- /dev/null +++ b/src/service/cadet/test_cadet_local_mq.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/test_cadet_local_mq.c | ||
23 | * @brief test cadet local: test of cadet channels with just one peer | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | |||
33 | #define TEST_MESSAGE_TYPE 1 | ||
34 | #define TEST_PORT_ID 1 | ||
35 | |||
36 | /** | ||
37 | * Test message structure. | ||
38 | */ | ||
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/service/cadet/valgrind-cadet.supp b/src/service/cadet/valgrind-cadet.supp new file mode 100644 index 000000000..fecd5185b --- /dev/null +++ b/src/service/cadet/valgrind-cadet.supp | |||
@@ -0,0 +1,116 @@ | |||
1 | { | ||
2 | logsetup_addr | ||
3 | Memcheck:Addr8 | ||
4 | obj:/lib/libc-2.14.1.so | ||
5 | ... | ||
6 | fun:get_type | ||
7 | fun:GNUNET_log_setup | ||
8 | fun:GNUNET_SERVICE_run | ||
9 | fun:main | ||
10 | } | ||
11 | |||
12 | { | ||
13 | scanf_addr | ||
14 | Memcheck:Addr8 | ||
15 | obj:/lib/libc-2.14.1.so | ||
16 | ... | ||
17 | fun:vsscanf | ||
18 | fun:sscanf | ||
19 | fun:GNUNET_CONFIGURATION_get_value_number | ||
20 | fun:GNUNET_SERVICE_get_server_addresses | ||
21 | fun:setup_service | ||
22 | fun:GNUNET_SERVICE_run | ||
23 | fun:main | ||
24 | } | ||
25 | |||
26 | { | ||
27 | mylog_addr | ||
28 | Memcheck:Addr8 | ||
29 | obj:/lib/libc-2.14.1.so | ||
30 | ... | ||
31 | fun:service_task | ||
32 | fun:GNUNET_SCHEDULER_run | ||
33 | fun:GNUNET_SERVICE_run | ||
34 | fun:main | ||
35 | } | ||
36 | |||
37 | { | ||
38 | mylog_uninit | ||
39 | Memcheck:Value8 | ||
40 | obj:/lib/libc-2.14.1.so | ||
41 | ... | ||
42 | fun:mylog | ||
43 | fun:GNUNET_log_from_nocheck | ||
44 | fun:service_task | ||
45 | ... | ||
46 | fun:GNUNET_SCHEDULER_run | ||
47 | fun:GNUNET_SERVICE_run | ||
48 | fun:main | ||
49 | } | ||
50 | |||
51 | { | ||
52 | mylog_from_cond | ||
53 | Memcheck:Cond | ||
54 | obj:/lib/libc-2.14.1.so | ||
55 | ... | ||
56 | fun:mylog | ||
57 | fun:GNUNET_log_from_nocheck | ||
58 | ... | ||
59 | fun:service_task | ||
60 | fun:GNUNET_SCHEDULER_run | ||
61 | fun:GNUNET_SERVICE_run | ||
62 | fun:main | ||
63 | } | ||
64 | |||
65 | { | ||
66 | mylog_cond | ||
67 | Memcheck:Cond | ||
68 | obj:/lib/libc-2.14.1.so | ||
69 | ... | ||
70 | fun:mylog | ||
71 | fun:GNUNET_log_nocheck | ||
72 | ... | ||
73 | fun:service_task | ||
74 | fun:GNUNET_SCHEDULER_run | ||
75 | fun:GNUNET_SERVICE_run | ||
76 | fun:main | ||
77 | } | ||
78 | |||
79 | { | ||
80 | inet_ntop_cond | ||
81 | Memcheck:Cond | ||
82 | obj:/lib/libc-2.14.1.so | ||
83 | ... | ||
84 | fun:inet_ntop | ||
85 | fun:GNUNET_a2s | ||
86 | ... | ||
87 | fun:service_task | ||
88 | fun:GNUNET_SCHEDULER_run | ||
89 | fun:GNUNET_SERVICE_run | ||
90 | fun:main | ||
91 | } | ||
92 | |||
93 | { | ||
94 | create_key_from_file | ||
95 | Memcheck:Addr8 | ||
96 | obj:/lib/libc-2.14.1.so | ||
97 | ... | ||
98 | fun:GNUNET_CRYPTO_rsa_key_create_from_file | ||
99 | fun:run | ||
100 | fun:service_task | ||
101 | fun:GNUNET_SCHEDULER_run | ||
102 | fun:GNUNET_SERVICE_run | ||
103 | fun:main | ||
104 | } | ||
105 | |||
106 | { | ||
107 | main_notify_handler | ||
108 | Memcheck:Addr8 | ||
109 | obj:/lib/libc-2.14.1.so | ||
110 | ... | ||
111 | fun:main_notify_handler | ||
112 | fun:receive_ready | ||
113 | fun:GNUNET_SCHEDULER_run | ||
114 | fun:GNUNET_SERVICE_run | ||
115 | fun:main | ||
116 | } \ No newline at end of file | ||