diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_core.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_core.c | 1348 |
1 files changed, 0 insertions, 1348 deletions
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c deleted file mode 100644 index 95a5d3f63..000000000 --- a/src/cadet/gnunet-service-cadet_core.c +++ /dev/null | |||
@@ -1,1348 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_core.c | ||
23 | * @brief cadet service; interaction with CORE service | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) | ||
28 | * | ||
29 | * TODO: | ||
30 | * - Optimization: given BROKEN messages, destroy paths (?) | ||
31 | */ | ||
32 | #include "platform.h" | ||
33 | #include "gnunet-service-cadet_core.h" | ||
34 | #include "gnunet-service-cadet_paths.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | #include "gnunet-service-cadet_connection.h" | ||
37 | #include "gnunet-service-cadet_tunnels.h" | ||
38 | #include "gnunet_core_service.h" | ||
39 | #include "gnunet_statistics_service.h" | ||
40 | #include "cadet_protocol.h" | ||
41 | |||
42 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-cor", __VA_ARGS__) | ||
43 | |||
44 | /** | ||
45 | * Information we keep per direction for a route. | ||
46 | */ | ||
47 | struct RouteDirection; | ||
48 | |||
49 | /** | ||
50 | * Set of CadetRoutes that have exactly the same number of messages | ||
51 | * in their buffer. Used so we can efficiently find all of those | ||
52 | * routes that have the current maximum of messages in the buffer (in | ||
53 | * case we have to purge). | ||
54 | */ | ||
55 | struct Rung | ||
56 | { | ||
57 | /** | ||
58 | * Rung of RouteDirections with one more buffer entry each. | ||
59 | */ | ||
60 | struct Rung *next; | ||
61 | |||
62 | /** | ||
63 | * Rung of RouteDirections with one less buffer entry each. | ||
64 | */ | ||
65 | struct Rung *prev; | ||
66 | |||
67 | /** | ||
68 | * DLL of route directions with a number of buffer entries matching this rung. | ||
69 | */ | ||
70 | struct RouteDirection *rd_head; | ||
71 | |||
72 | /** | ||
73 | * DLL of route directions with a number of buffer entries matching this rung. | ||
74 | */ | ||
75 | struct RouteDirection *rd_tail; | ||
76 | |||
77 | /** | ||
78 | * Total number of route directions in this rung. | ||
79 | */ | ||
80 | unsigned int num_routes; | ||
81 | |||
82 | /** | ||
83 | * Number of messages route directions at this rung have | ||
84 | * in their buffer. | ||
85 | */ | ||
86 | unsigned int rung_off; | ||
87 | }; | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Information we keep per direction for a route. | ||
92 | */ | ||
93 | struct RouteDirection | ||
94 | { | ||
95 | /** | ||
96 | * DLL of other route directions within the same `struct Rung`. | ||
97 | */ | ||
98 | struct RouteDirection *prev; | ||
99 | |||
100 | /** | ||
101 | * DLL of other route directions within the same `struct Rung`. | ||
102 | */ | ||
103 | struct RouteDirection *next; | ||
104 | |||
105 | /** | ||
106 | * Rung of this route direction (matches length of the buffer DLL). | ||
107 | */ | ||
108 | struct Rung *rung; | ||
109 | |||
110 | /** | ||
111 | * Head of DLL of envelopes we have in the buffer for this direction. | ||
112 | */ | ||
113 | struct GNUNET_MQ_Envelope *env_head; | ||
114 | |||
115 | /** | ||
116 | * Tail of DLL of envelopes we have in the buffer for this direction. | ||
117 | */ | ||
118 | struct GNUNET_MQ_Envelope *env_tail; | ||
119 | |||
120 | /** | ||
121 | * Target peer. | ||
122 | */ | ||
123 | struct CadetPeer *hop; | ||
124 | |||
125 | /** | ||
126 | * Route this direction is part of. | ||
127 | */ | ||
128 | struct CadetRoute *my_route; | ||
129 | |||
130 | /** | ||
131 | * Message queue manager for @e hop. | ||
132 | */ | ||
133 | struct GCP_MessageQueueManager *mqm; | ||
134 | |||
135 | /** | ||
136 | * Is @e mqm currently ready for transmission? | ||
137 | */ | ||
138 | int is_ready; | ||
139 | }; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Description of a segment of a `struct CadetConnection` at the | ||
144 | * intermediate peers. Routes are basically entries in a peer's | ||
145 | * routing table for forwarding traffic. At both endpoints, the | ||
146 | * routes are terminated by a `struct CadetConnection`, which knows | ||
147 | * the complete `struct CadetPath` that is formed by the individual | ||
148 | * routes. | ||
149 | */ | ||
150 | struct CadetRoute | ||
151 | { | ||
152 | /** | ||
153 | * Information about the next hop on this route. | ||
154 | */ | ||
155 | struct RouteDirection next; | ||
156 | |||
157 | /** | ||
158 | * Information about the previous hop on this route. | ||
159 | */ | ||
160 | struct RouteDirection prev; | ||
161 | |||
162 | /** | ||
163 | * Unique identifier for the connection that uses this route. | ||
164 | */ | ||
165 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
166 | |||
167 | /** | ||
168 | * When was this route last in use? | ||
169 | */ | ||
170 | struct GNUNET_TIME_Absolute last_use; | ||
171 | |||
172 | /** | ||
173 | * Position of this route in the #route_heap. | ||
174 | */ | ||
175 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
176 | }; | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Handle to the CORE service. | ||
181 | */ | ||
182 | static struct GNUNET_CORE_Handle *core; | ||
183 | |||
184 | /** | ||
185 | * Routes on which this peer is an intermediate. | ||
186 | */ | ||
187 | static struct GNUNET_CONTAINER_MultiShortmap *routes; | ||
188 | |||
189 | /** | ||
190 | * Heap of routes, MIN-sorted by last activity. | ||
191 | */ | ||
192 | static struct GNUNET_CONTAINER_Heap *route_heap; | ||
193 | |||
194 | /** | ||
195 | * Rung zero (always pointed to by #rung_head). | ||
196 | */ | ||
197 | static struct Rung rung_zero; | ||
198 | |||
199 | /** | ||
200 | * DLL of rungs, with the head always point to a rung of | ||
201 | * route directions with no messages in the queue. | ||
202 | */ | ||
203 | static struct Rung *rung_head = &rung_zero; | ||
204 | |||
205 | /** | ||
206 | * Tail of the #rung_head DLL. | ||
207 | */ | ||
208 | static struct Rung *rung_tail = &rung_zero; | ||
209 | |||
210 | /** | ||
211 | * Maximum number of concurrent routes this peer will support. | ||
212 | */ | ||
213 | static unsigned long long max_routes; | ||
214 | |||
215 | /** | ||
216 | * Maximum number of envelopes we will buffer at this peer. | ||
217 | */ | ||
218 | static unsigned long long max_buffers; | ||
219 | |||
220 | /** | ||
221 | * Current number of envelopes we have buffered at this peer. | ||
222 | */ | ||
223 | static unsigned long long cur_buffers; | ||
224 | |||
225 | /** | ||
226 | * Task to timeout routes. | ||
227 | */ | ||
228 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
229 | |||
230 | /** | ||
231 | * Get the route corresponding to a hash. | ||
232 | * | ||
233 | * @param cid hash generated from the connection identifier | ||
234 | */ | ||
235 | static struct CadetRoute * | ||
236 | get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
237 | { | ||
238 | return GNUNET_CONTAINER_multishortmap_get (routes, | ||
239 | &cid->connection_of_tunnel); | ||
240 | } | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Lower the rung in which @a dir is by 1. | ||
245 | * | ||
246 | * @param dir direction to lower in rung. | ||
247 | */ | ||
248 | static void | ||
249 | lower_rung (struct RouteDirection *dir) | ||
250 | { | ||
251 | struct Rung *rung = dir->rung; | ||
252 | struct Rung *prev; | ||
253 | |||
254 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
255 | prev = rung->prev; | ||
256 | GNUNET_assert (NULL != prev); | ||
257 | if (prev->rung_off != rung->rung_off - 1) | ||
258 | { | ||
259 | prev = GNUNET_new (struct Rung); | ||
260 | prev->rung_off = rung->rung_off - 1; | ||
261 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev); | ||
262 | } | ||
263 | GNUNET_assert (NULL != prev); | ||
264 | GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir); | ||
265 | dir->rung = prev; | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Discard the buffer @a env from the route direction @a dir and | ||
271 | * move @a dir down a rung. | ||
272 | * | ||
273 | * @param dir direction that contains the @a env in the buffer | ||
274 | * @param env envelope to discard | ||
275 | */ | ||
276 | static void | ||
277 | discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env) | ||
278 | { | ||
279 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
280 | cur_buffers--; | ||
281 | GNUNET_MQ_discard (env); | ||
282 | lower_rung (dir); | ||
283 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
284 | } | ||
285 | |||
286 | |||
287 | /** | ||
288 | * Discard all messages from the highest rung, to make space. | ||
289 | */ | ||
290 | static void | ||
291 | discard_all_from_rung_tail () | ||
292 | { | ||
293 | struct Rung *tail = rung_tail; | ||
294 | struct RouteDirection *dir; | ||
295 | |||
296 | while (NULL != (dir = tail->rd_head)) | ||
297 | { | ||
298 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
299 | "Queue full due new message on connection %s, dropping old message\n", | ||
300 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
301 | GNUNET_STATISTICS_update (stats, | ||
302 | "# messages dropped due to full buffer", | ||
303 | 1, | ||
304 | GNUNET_NO); | ||
305 | discard_buffer (dir, dir->env_head); | ||
306 | } | ||
307 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail); | ||
308 | GNUNET_free (tail); | ||
309 | } | ||
310 | |||
311 | |||
312 | /** | ||
313 | * We message @a msg from @a prev. Find its route by @a cid and | ||
314 | * forward to the next hop. Drop and signal broken route if we do not | ||
315 | * have a route. | ||
316 | * | ||
317 | * @param prev previous hop (sender) | ||
318 | * @param cid connection identifier, tells us which route to use | ||
319 | * @param msg the message to forward | ||
320 | */ | ||
321 | static void | ||
322 | route_message (struct CadetPeer *prev, | ||
323 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
324 | const struct GNUNET_MessageHeader *msg, | ||
325 | const enum GNUNET_MQ_PriorityPreferences priority) | ||
326 | { | ||
327 | struct CadetRoute *route; | ||
328 | struct RouteDirection *dir; | ||
329 | struct Rung *rung; | ||
330 | struct Rung *nxt; | ||
331 | struct GNUNET_MQ_Envelope *env; | ||
332 | |||
333 | route = get_route (cid); | ||
334 | if (NULL == route) | ||
335 | { | ||
336 | struct GNUNET_MQ_Envelope *env; | ||
337 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
338 | |||
339 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "Failed to route message of type %u from %s on connection %s: no route\n", | ||
341 | ntohs (msg->type), | ||
342 | GCP_2s (prev), | ||
343 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
344 | switch (ntohs (msg->type)) | ||
345 | { | ||
346 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
347 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
348 | /* No need to respond to these! */ | ||
349 | return; | ||
350 | } | ||
351 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
352 | bm->cid = *cid; | ||
353 | bm->peer1 = my_full_id; | ||
354 | GCP_send_ooo (prev, env); | ||
355 | return; | ||
356 | } | ||
357 | route->last_use = GNUNET_TIME_absolute_get (); | ||
358 | GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us); | ||
359 | dir = (prev == route->prev.hop) ? &route->next : &route->prev; | ||
360 | if (GNUNET_YES == dir->is_ready) | ||
361 | { | ||
362 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
363 | "Routing message of type %u from %s to %s on connection %s\n", | ||
364 | ntohs (msg->type), | ||
365 | GCP_2s (prev), | ||
366 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
367 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
368 | dir->is_ready = GNUNET_NO; | ||
369 | GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg)); | ||
370 | return; | ||
371 | } | ||
372 | /* Check if low latency is required and if the previous message was | ||
373 | unreliable; if so, make sure we only queue one message per | ||
374 | direction (no buffering). */ | ||
375 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
376 | (NULL != dir->env_head) && | ||
377 | (0 == | ||
378 | (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE))) | ||
379 | discard_buffer (dir, dir->env_head); | ||
380 | /* Check for duplicates */ | ||
381 | for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env; | ||
382 | env = GNUNET_MQ_env_next (env)) | ||
383 | { | ||
384 | const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env); | ||
385 | |||
386 | if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size)))) | ||
387 | { | ||
388 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
389 | "Received duplicate of message already in buffer, dropping\n"); | ||
390 | GNUNET_STATISTICS_update (stats, | ||
391 | "# messages dropped due to duplicate in buffer", | ||
392 | 1, | ||
393 | GNUNET_NO); | ||
394 | return; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | rung = dir->rung; | ||
399 | if (cur_buffers == max_buffers) | ||
400 | { | ||
401 | /* Need to make room. */ | ||
402 | if (NULL != rung->next) | ||
403 | { | ||
404 | /* Easy case, drop messages from route directions in highest rung */ | ||
405 | discard_all_from_rung_tail (); | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | /* We are in the highest rung, drop our own! */ | ||
410 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
411 | "Queue full due new message on connection %s, dropping old message\n", | ||
412 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
413 | GNUNET_STATISTICS_update (stats, | ||
414 | "# messages dropped due to full buffer", | ||
415 | 1, | ||
416 | GNUNET_NO); | ||
417 | discard_buffer (dir, dir->env_head); | ||
418 | rung = dir->rung; | ||
419 | } | ||
420 | } | ||
421 | /* remove 'dir' from current rung */ | ||
422 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
423 | /* make 'nxt' point to the next higher rung, create if necessary */ | ||
424 | nxt = rung->next; | ||
425 | if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off)) | ||
426 | { | ||
427 | nxt = GNUNET_new (struct Rung); | ||
428 | nxt->rung_off = rung->rung_off + 1; | ||
429 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt); | ||
430 | } | ||
431 | /* insert 'dir' into next higher rung */ | ||
432 | GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir); | ||
433 | dir->rung = nxt; | ||
434 | |||
435 | /* add message into 'dir' buffer */ | ||
436 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
437 | "Queueing new message of type %u from %s to %s on connection %s\n", | ||
438 | ntohs (msg->type), | ||
439 | GCP_2s (prev), | ||
440 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
441 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
442 | env = GNUNET_MQ_msg_copy (msg); | ||
443 | GNUNET_MQ_env_set_options (env, priority); | ||
444 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
445 | (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) && | ||
446 | (NULL != dir->env_head) && | ||
447 | (0 == (GNUNET_MQ_env_get_options (dir->env_head) | ||
448 | & GNUNET_MQ_PREF_LOW_LATENCY))) | ||
449 | GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env); | ||
450 | else | ||
451 | GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env); | ||
452 | cur_buffers++; | ||
453 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
454 | /* Clean up 'rung' if now empty (and not head) */ | ||
455 | if ((NULL == rung->rd_head) && (rung != rung_head)) | ||
456 | { | ||
457 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung); | ||
458 | GNUNET_free (rung); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Check if the create_connection message has the appropriate size. | ||
465 | * | ||
466 | * @param cls Closure (unused). | ||
467 | * @param msg Message to check. | ||
468 | * | ||
469 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
470 | */ | ||
471 | static int | ||
472 | check_connection_create (void *cls, | ||
473 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
474 | { | ||
475 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
476 | |||
477 | if (0 != (size % sizeof(struct GNUNET_PeerIdentity))) | ||
478 | { | ||
479 | GNUNET_break_op (0); | ||
480 | return GNUNET_NO; | ||
481 | } | ||
482 | return GNUNET_YES; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Free internal data of a route direction. | ||
488 | * | ||
489 | * @param dir direction to destroy (do NOT free memory of 'dir' itself) | ||
490 | */ | ||
491 | static void | ||
492 | destroy_direction (struct RouteDirection *dir) | ||
493 | { | ||
494 | struct GNUNET_MQ_Envelope *env; | ||
495 | |||
496 | while (NULL != (env = dir->env_head)) | ||
497 | { | ||
498 | GNUNET_STATISTICS_update (stats, | ||
499 | "# messages dropped due to route destruction", | ||
500 | 1, | ||
501 | GNUNET_NO); | ||
502 | discard_buffer (dir, env); | ||
503 | } | ||
504 | if (NULL != dir->mqm) | ||
505 | { | ||
506 | GCP_request_mq_cancel (dir->mqm, NULL); | ||
507 | dir->mqm = NULL; | ||
508 | } | ||
509 | GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir); | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Destroy our state for @a route. | ||
515 | * | ||
516 | * @param route route to destroy | ||
517 | */ | ||
518 | static void | ||
519 | destroy_route (struct CadetRoute *route) | ||
520 | { | ||
521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
522 | "Destroying route from %s to %s of connection %s\n", | ||
523 | GNUNET_i2s (GCP_get_id (route->prev.hop)), | ||
524 | GNUNET_i2s2 (GCP_get_id (route->next.hop)), | ||
525 | GNUNET_sh2s (&route->cid.connection_of_tunnel)); | ||
526 | GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn)); | ||
527 | GNUNET_assert ( | ||
528 | GNUNET_YES == | ||
529 | GNUNET_CONTAINER_multishortmap_remove (routes, | ||
530 | &route->cid.connection_of_tunnel, | ||
531 | route)); | ||
532 | GNUNET_STATISTICS_set (stats, | ||
533 | "# routes", | ||
534 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
535 | GNUNET_NO); | ||
536 | destroy_direction (&route->prev); | ||
537 | destroy_direction (&route->next); | ||
538 | GNUNET_free (route); | ||
539 | } | ||
540 | |||
541 | |||
542 | /** | ||
543 | * Send message that a route is broken between @a peer1 and @a peer2. | ||
544 | * | ||
545 | * @param target where to send the message | ||
546 | * @param cid connection identifier to use | ||
547 | * @param peer1 one of the peers where a link is broken | ||
548 | * @param peer2 another one of the peers where a link is broken | ||
549 | */ | ||
550 | static void | ||
551 | send_broken (struct RouteDirection *target, | ||
552 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
553 | const struct GNUNET_PeerIdentity *peer1, | ||
554 | const struct GNUNET_PeerIdentity *peer2) | ||
555 | { | ||
556 | struct GNUNET_MQ_Envelope *env; | ||
557 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
558 | |||
559 | if (NULL == target->mqm) | ||
560 | return; /* Can't send notification, connection is down! */ | ||
561 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
562 | "Notifying %s about BROKEN route at %s-%s of connection %s\n", | ||
563 | GCP_2s (target->hop), | ||
564 | GNUNET_i2s (peer1), | ||
565 | GNUNET_i2s2 (peer2), | ||
566 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
567 | |||
568 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
569 | bm->cid = *cid; | ||
570 | if (NULL != peer1) | ||
571 | bm->peer1 = *peer1; | ||
572 | if (NULL != peer2) | ||
573 | bm->peer2 = *peer2; | ||
574 | GCP_request_mq_cancel (target->mqm, env); | ||
575 | target->mqm = NULL; | ||
576 | } | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Function called to check if any routes have timed out, and if | ||
581 | * so, to clean them up. Finally, schedules itself again at the | ||
582 | * earliest time where there might be more work. | ||
583 | * | ||
584 | * @param cls NULL | ||
585 | */ | ||
586 | static void | ||
587 | timeout_cb (void *cls) | ||
588 | { | ||
589 | struct CadetRoute *r; | ||
590 | struct GNUNET_TIME_Relative linger; | ||
591 | struct GNUNET_TIME_Absolute exp; | ||
592 | |||
593 | timeout_task = NULL; | ||
594 | linger = GNUNET_TIME_relative_multiply (keepalive_period, 3); | ||
595 | while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap))) | ||
596 | { | ||
597 | exp = GNUNET_TIME_absolute_add (r->last_use, linger); | ||
598 | if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) | ||
599 | { | ||
600 | /* Route not yet timed out, wait until it does. */ | ||
601 | timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL); | ||
602 | return; | ||
603 | } | ||
604 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
605 | "Sending BROKEN due to timeout (%s was last use, %s linger)\n", | ||
606 | GNUNET_STRINGS_absolute_time_to_string (r->last_use), | ||
607 | GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES)); | ||
608 | send_broken (&r->prev, &r->cid, NULL, NULL); | ||
609 | send_broken (&r->next, &r->cid, NULL, NULL); | ||
610 | destroy_route (r); | ||
611 | } | ||
612 | /* No more routes left, so no need for a #timeout_task */ | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
617 | * Function called when the message queue to the previous hop | ||
618 | * becomes available/unavailable. We expect this function to | ||
619 | * be called immediately when we register, and then again | ||
620 | * later if the connection ever goes down. | ||
621 | * | ||
622 | * @param cls the `struct RouteDirection` | ||
623 | * @param available #GNUNET_YES if sending is now possible, | ||
624 | * #GNUNET_NO if sending is no longer possible | ||
625 | * #GNUNET_SYSERR if sending is no longer possible | ||
626 | * and the last envelope was discarded | ||
627 | */ | ||
628 | static void | ||
629 | dir_ready_cb (void *cls, int ready) | ||
630 | { | ||
631 | struct RouteDirection *dir = cls; | ||
632 | struct CadetRoute *route = dir->my_route; | ||
633 | struct RouteDirection *odir; | ||
634 | |||
635 | if (GNUNET_YES == ready) | ||
636 | { | ||
637 | struct GNUNET_MQ_Envelope *env; | ||
638 | |||
639 | dir->is_ready = GNUNET_YES; | ||
640 | if (NULL != (env = dir->env_head)) | ||
641 | { | ||
642 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
643 | cur_buffers--; | ||
644 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
645 | lower_rung (dir); | ||
646 | dir->is_ready = GNUNET_NO; | ||
647 | GCP_send (dir->mqm, env); | ||
648 | } | ||
649 | return; | ||
650 | } | ||
651 | odir = (dir == &route->next) ? &route->prev : &route->next; | ||
652 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n"); | ||
653 | send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id); | ||
654 | destroy_route (route); | ||
655 | } | ||
656 | |||
657 | |||
658 | /** | ||
659 | * Initialize one of the directions of a route. | ||
660 | * | ||
661 | * @param route route the direction belongs to | ||
662 | * @param dir direction to initialize | ||
663 | * @param hop next hop on in the @a dir | ||
664 | */ | ||
665 | static void | ||
666 | dir_init (struct RouteDirection *dir, | ||
667 | struct CadetRoute *route, | ||
668 | struct CadetPeer *hop) | ||
669 | { | ||
670 | dir->hop = hop; | ||
671 | dir->my_route = route; | ||
672 | dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir); | ||
673 | GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir); | ||
674 | dir->rung = rung_head; | ||
675 | GNUNET_assert (GNUNET_YES == dir->is_ready); | ||
676 | } | ||
677 | |||
678 | |||
679 | /** | ||
680 | * We could not create the desired route. Send a | ||
681 | * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
682 | * message to @a target. | ||
683 | * | ||
684 | * @param target who should receive the message | ||
685 | * @param cid identifier of the connection/route that failed | ||
686 | * @param failure_at neighbour with which we failed to route, | ||
687 | * or NULL. | ||
688 | */ | ||
689 | static void | ||
690 | send_broken_without_mqm ( | ||
691 | struct CadetPeer *target, | ||
692 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
693 | const struct GNUNET_PeerIdentity *failure_at) | ||
694 | { | ||
695 | struct GNUNET_MQ_Envelope *env; | ||
696 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
697 | |||
698 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
699 | bm->cid = *cid; | ||
700 | bm->peer1 = my_full_id; | ||
701 | if (NULL != failure_at) | ||
702 | bm->peer2 = *failure_at; | ||
703 | GCP_send_ooo (target, env); | ||
704 | } | ||
705 | |||
706 | |||
707 | /** | ||
708 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | ||
709 | * | ||
710 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
711 | * @param msg Message itself. | ||
712 | */ | ||
713 | static void | ||
714 | handle_connection_create ( | ||
715 | void *cls, | ||
716 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
717 | { | ||
718 | struct CadetPeer *sender = cls; | ||
719 | struct CadetPeer *next; | ||
720 | const struct GNUNET_PeerIdentity *pids = | ||
721 | (const struct GNUNET_PeerIdentity *) &msg[1]; | ||
722 | struct CadetRoute *route; | ||
723 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
724 | unsigned int path_length; | ||
725 | unsigned int off; | ||
726 | struct CadetTunnel *t; | ||
727 | |||
728 | path_length = size / sizeof(struct GNUNET_PeerIdentity); | ||
729 | if (0 == path_length) | ||
730 | { | ||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "Dropping CADET_CONNECTION_CREATE with empty path\n"); | ||
733 | GNUNET_break_op (0); | ||
734 | return; | ||
735 | } | ||
736 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
737 | "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n", | ||
738 | GCP_2s (sender), | ||
739 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
740 | path_length); | ||
741 | /* Check for loops */ | ||
742 | { | ||
743 | struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
744 | |||
745 | map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES); | ||
746 | GNUNET_assert (NULL != map); | ||
747 | for (unsigned int i = 0; i < path_length; i++) | ||
748 | { | ||
749 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
750 | "CADET_CONNECTION_CREATE has peer %s at offset %u\n", | ||
751 | GNUNET_i2s (&pids[i]), | ||
752 | i); | ||
753 | if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put ( | ||
754 | map, | ||
755 | &pids[i], | ||
756 | NULL, | ||
757 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
758 | { | ||
759 | /* bogus request */ | ||
760 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
761 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
762 | "Dropping CADET_CONNECTION_CREATE with cyclic path\n"); | ||
763 | GNUNET_break_op (0); | ||
764 | return; | ||
765 | } | ||
766 | } | ||
767 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
768 | } | ||
769 | /* Initiator is at offset 0, find us */ | ||
770 | for (off = 1; off < path_length; off++) | ||
771 | if (0 == GNUNET_memcmp (&my_full_id, &pids[off])) | ||
772 | break; | ||
773 | if (off == path_length) | ||
774 | { | ||
775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
776 | "Dropping CADET_CONNECTION_CREATE without us in the path\n"); | ||
777 | GNUNET_break_op (0); | ||
778 | return; | ||
779 | } | ||
780 | /* Check previous hop */ | ||
781 | if (sender != GCP_get (&pids[off - 1], GNUNET_NO)) | ||
782 | { | ||
783 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
784 | "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n"); | ||
785 | GNUNET_break_op (0); | ||
786 | return; | ||
787 | } | ||
788 | if (NULL != (route = get_route (&msg->cid))) | ||
789 | { | ||
790 | /* Duplicate CREATE, pass it on, previous one might have been lost! */ | ||
791 | |||
792 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
793 | "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
794 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
795 | route_message (sender, | ||
796 | &msg->cid, | ||
797 | &msg->header, | ||
798 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | ||
799 | | GNUNET_MQ_PREF_LOW_LATENCY); | ||
800 | return; | ||
801 | } | ||
802 | if (off == path_length - 1) | ||
803 | { | ||
804 | /* We are the destination, create connection */ | ||
805 | struct CadetConnection *cc; | ||
806 | struct CadetPeerPath *path; | ||
807 | struct CadetPeer *origin; | ||
808 | |||
809 | cc = GCC_lookup (&msg->cid); | ||
810 | if (NULL != cc) | ||
811 | { | ||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
814 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
815 | GCC_handle_duplicate_create (cc); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | origin = GCP_get (&pids[0], GNUNET_YES); | ||
820 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
821 | "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n", | ||
822 | GCP_2s (origin), | ||
823 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
824 | path = GCPP_get_path_from_route (path_length - 1, pids); | ||
825 | t = GCP_get_tunnel (origin, GNUNET_YES); | ||
826 | |||
827 | // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss) | ||
828 | if ((GNUNET_YES == msg->has_monotime) && | ||
829 | (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) && | ||
830 | (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) && | ||
831 | (CADET_TUNNEL_KEY_OK == GCT_get_estate (t))) | ||
832 | { | ||
833 | GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED); | ||
834 | } | ||
835 | |||
836 | if (GNUNET_OK != | ||
837 | GCT_add_inbound_connection (t, | ||
838 | &msg->cid, | ||
839 | path)) | ||
840 | { | ||
841 | /* Send back BROKEN: duplicate connection on the same path, | ||
842 | we will use the other one. */ | ||
843 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
844 | "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n", | ||
845 | GCP_2s (sender), | ||
846 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
847 | GCPP_2s (path)); | ||
848 | send_broken_without_mqm (sender, &msg->cid, NULL); | ||
849 | return; | ||
850 | } | ||
851 | return; | ||
852 | } | ||
853 | /* We are merely a hop on the way, check if we can support the route */ | ||
854 | next = GCP_get (&pids[off + 1], GNUNET_NO); | ||
855 | if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next))) | ||
856 | { | ||
857 | /* unworkable, send back BROKEN notification */ | ||
858 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
859 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", | ||
860 | GCP_2s (sender), | ||
861 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
862 | GNUNET_i2s (&pids[off + 1]), | ||
863 | off + 1); | ||
864 | send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]); | ||
865 | return; | ||
866 | } | ||
867 | if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes)) | ||
868 | { | ||
869 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
870 | "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n", | ||
871 | GCP_2s (sender), | ||
872 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
873 | send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]); | ||
874 | return; | ||
875 | } | ||
876 | |||
877 | /* Workable route, create routing entry */ | ||
878 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
879 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n", | ||
880 | GCP_2s (sender), | ||
881 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
882 | GNUNET_i2s (&pids[off + 1]), | ||
883 | off + 1); | ||
884 | route = GNUNET_new (struct CadetRoute); | ||
885 | route->cid = msg->cid; | ||
886 | route->last_use = GNUNET_TIME_absolute_get (); | ||
887 | dir_init (&route->prev, route, sender); | ||
888 | dir_init (&route->next, route, next); | ||
889 | GNUNET_assert (GNUNET_OK == | ||
890 | GNUNET_CONTAINER_multishortmap_put ( | ||
891 | routes, | ||
892 | &route->cid.connection_of_tunnel, | ||
893 | route, | ||
894 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
895 | GNUNET_STATISTICS_set (stats, | ||
896 | "# routes", | ||
897 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
898 | GNUNET_NO); | ||
899 | route->hn = GNUNET_CONTAINER_heap_insert (route_heap, | ||
900 | route, | ||
901 | route->last_use.abs_value_us); | ||
902 | if (NULL == timeout_task) | ||
903 | timeout_task = | ||
904 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
905 | keepalive_period, | ||
906 | 3), | ||
907 | &timeout_cb, | ||
908 | NULL); | ||
909 | /* also pass CREATE message along to next hop */ | ||
910 | route_message (sender, | ||
911 | &msg->cid, | ||
912 | &msg->header, | ||
913 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
914 | } | ||
915 | |||
916 | |||
917 | /** | ||
918 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK | ||
919 | * | ||
920 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
921 | * @param msg Message itself. | ||
922 | */ | ||
923 | static void | ||
924 | handle_connection_create_ack ( | ||
925 | void *cls, | ||
926 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | ||
927 | { | ||
928 | struct CadetPeer *peer = cls; | ||
929 | struct CadetConnection *cc; | ||
930 | |||
931 | /* First, check if ACK belongs to a connection that ends here. */ | ||
932 | cc = GCC_lookup (&msg->cid); | ||
933 | if (NULL != cc) | ||
934 | { | ||
935 | /* verify ACK came from the right direction */ | ||
936 | unsigned int len; | ||
937 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
938 | |||
939 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
940 | { | ||
941 | /* received ACK from unexpected direction, ignore! */ | ||
942 | GNUNET_break_op (0); | ||
943 | return; | ||
944 | } | ||
945 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
946 | "Received CONNECTION_CREATE_ACK for connection %s.\n", | ||
947 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
948 | GCC_handle_connection_create_ack (cc); | ||
949 | return; | ||
950 | } | ||
951 | |||
952 | /* We're just an intermediary peer, route the message along its path */ | ||
953 | route_message (peer, | ||
954 | &msg->cid, | ||
955 | &msg->header, | ||
956 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
962 | * | ||
963 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
964 | * @param msg Message itself. | ||
965 | * @deprecated duplicate logic with #handle_destroy(); dedup! | ||
966 | */ | ||
967 | static void | ||
968 | handle_connection_broken ( | ||
969 | void *cls, | ||
970 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | ||
971 | { | ||
972 | struct CadetPeer *peer = cls; | ||
973 | struct CadetConnection *cc; | ||
974 | struct CadetRoute *route; | ||
975 | |||
976 | /* First, check if message belongs to a connection that ends here. */ | ||
977 | cc = GCC_lookup (&msg->cid); | ||
978 | if (NULL != cc) | ||
979 | { | ||
980 | /* verify message came from the right direction */ | ||
981 | unsigned int len; | ||
982 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
983 | |||
984 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
985 | { | ||
986 | /* received message from unexpected direction, ignore! */ | ||
987 | GNUNET_break_op (0); | ||
988 | return; | ||
989 | } | ||
990 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
991 | "Received CONNECTION_BROKEN for connection %s. Destroying it.\n", | ||
992 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
993 | GCC_destroy_without_core (cc); | ||
994 | |||
995 | /* FIXME: also destroy the path up to the specified link! */ | ||
996 | return; | ||
997 | } | ||
998 | |||
999 | /* We're just an intermediary peer, route the message along its path */ | ||
1000 | route_message (peer, | ||
1001 | &msg->cid, | ||
1002 | &msg->header, | ||
1003 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
1004 | route = get_route (&msg->cid); | ||
1005 | if (NULL != route) | ||
1006 | destroy_route (route); | ||
1007 | /* FIXME: also destroy paths we MAY have up to the specified link! */ | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /** | ||
1012 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY | ||
1013 | * | ||
1014 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1015 | * @param msg Message itself. | ||
1016 | */ | ||
1017 | static void | ||
1018 | handle_connection_destroy ( | ||
1019 | void *cls, | ||
1020 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | ||
1021 | { | ||
1022 | struct CadetPeer *peer = cls; | ||
1023 | struct CadetConnection *cc; | ||
1024 | struct CadetRoute *route; | ||
1025 | |||
1026 | /* First, check if message belongs to a connection that ends here. */ | ||
1027 | cc = GCC_lookup (&msg->cid); | ||
1028 | if (NULL != cc) | ||
1029 | { | ||
1030 | /* verify message came from the right direction */ | ||
1031 | unsigned int len; | ||
1032 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1033 | |||
1034 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1035 | { | ||
1036 | /* received message from unexpected direction, ignore! */ | ||
1037 | GNUNET_break_op (0); | ||
1038 | return; | ||
1039 | } | ||
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1041 | "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n", | ||
1042 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1043 | |||
1044 | GCC_destroy_without_core (cc); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | /* We're just an intermediary peer, route the message along its path */ | ||
1049 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1050 | "Received CONNECTION_DESTROY for connection %s. Destroying route.\n", | ||
1051 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1052 | route_message (peer, | ||
1053 | &msg->cid, | ||
1054 | &msg->header, | ||
1055 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
1056 | route = get_route (&msg->cid); | ||
1057 | if (NULL != route) | ||
1058 | destroy_route (route); | ||
1059 | } | ||
1060 | |||
1061 | |||
1062 | /** | ||
1063 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX | ||
1064 | * | ||
1065 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1066 | * @param msg Message itself. | ||
1067 | */ | ||
1068 | static void | ||
1069 | handle_tunnel_kx (void *cls, | ||
1070 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1071 | { | ||
1072 | struct CadetPeer *peer = cls; | ||
1073 | struct CadetConnection *cc; | ||
1074 | |||
1075 | /* First, check if message belongs to a connection that ends here. */ | ||
1076 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1077 | "Routing KX with ephemeral %s on CID %s\n", | ||
1078 | GNUNET_e2s (&msg->ephemeral_key), | ||
1079 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1080 | |||
1081 | |||
1082 | cc = GCC_lookup (&msg->cid); | ||
1083 | if (NULL != cc) | ||
1084 | { | ||
1085 | /* verify message came from the right direction */ | ||
1086 | unsigned int len; | ||
1087 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1088 | |||
1089 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1090 | { | ||
1091 | /* received message from unexpected direction, ignore! */ | ||
1092 | GNUNET_break_op (0); | ||
1093 | return; | ||
1094 | } | ||
1095 | GCC_handle_kx (cc, msg); | ||
1096 | return; | ||
1097 | } | ||
1098 | |||
1099 | /* We're just an intermediary peer, route the message along its path */ | ||
1100 | route_message (peer, | ||
1101 | &msg->cid, | ||
1102 | &msg->header, | ||
1103 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1104 | } | ||
1105 | |||
1106 | |||
1107 | /** | ||
1108 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH | ||
1109 | * | ||
1110 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1111 | * @param msg Message itself. | ||
1112 | */ | ||
1113 | static void | ||
1114 | handle_tunnel_kx_auth ( | ||
1115 | void *cls, | ||
1116 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1117 | { | ||
1118 | struct CadetPeer *peer = cls; | ||
1119 | struct CadetConnection *cc; | ||
1120 | |||
1121 | /* First, check if message belongs to a connection that ends here. */ | ||
1122 | cc = GCC_lookup (&msg->kx.cid); | ||
1123 | if (NULL != cc) | ||
1124 | { | ||
1125 | /* verify message came from the right direction */ | ||
1126 | unsigned int len; | ||
1127 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1128 | |||
1129 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1130 | { | ||
1131 | /* received message from unexpected direction, ignore! */ | ||
1132 | GNUNET_break_op (0); | ||
1133 | return; | ||
1134 | } | ||
1135 | GCC_handle_kx_auth (cc, msg); | ||
1136 | return; | ||
1137 | } | ||
1138 | |||
1139 | /* We're just an intermediary peer, route the message along its path */ | ||
1140 | route_message (peer, | ||
1141 | &msg->kx.cid, | ||
1142 | &msg->kx.header, | ||
1143 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1144 | } | ||
1145 | |||
1146 | |||
1147 | /** | ||
1148 | * Check if the encrypted message has the appropriate size. | ||
1149 | * | ||
1150 | * @param cls Closure (unused). | ||
1151 | * @param msg Message to check. | ||
1152 | * | ||
1153 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
1154 | */ | ||
1155 | static int | ||
1156 | check_tunnel_encrypted (void *cls, | ||
1157 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1158 | { | ||
1159 | return GNUNET_YES; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | /** | ||
1164 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. | ||
1165 | * | ||
1166 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1167 | * @param msg Message itself. | ||
1168 | */ | ||
1169 | static void | ||
1170 | handle_tunnel_encrypted (void *cls, | ||
1171 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1172 | { | ||
1173 | struct CadetPeer *peer = cls; | ||
1174 | struct CadetConnection *cc; | ||
1175 | |||
1176 | /* First, check if message belongs to a connection that ends here. */ | ||
1177 | cc = GCC_lookup (&msg->cid); | ||
1178 | if (NULL != cc) | ||
1179 | { | ||
1180 | /* verify message came from the right direction */ | ||
1181 | unsigned int len; | ||
1182 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1183 | |||
1184 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1185 | { | ||
1186 | /* received message from unexpected direction, ignore! */ | ||
1187 | GNUNET_break_op (0); | ||
1188 | return; | ||
1189 | } | ||
1190 | GCC_handle_encrypted (cc, msg); | ||
1191 | return; | ||
1192 | } | ||
1193 | /* We're just an intermediary peer, route the message along its path */ | ||
1194 | route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT); | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | /** | ||
1199 | * Function called after #GNUNET_CORE_connect has succeeded (or failed | ||
1200 | * for good). Note that the private key of the peer is intentionally | ||
1201 | * not exposed here; if you need it, your process should try to read | ||
1202 | * the private key file directly (which should work if you are | ||
1203 | * authorized...). Implementations of this function must not call | ||
1204 | * #GNUNET_CORE_disconnect (other than by scheduling a new task to | ||
1205 | * do this later). | ||
1206 | * | ||
1207 | * @param cls closure | ||
1208 | * @param my_identity ID of this peer, NULL if we failed | ||
1209 | */ | ||
1210 | static void | ||
1211 | core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) | ||
1212 | { | ||
1213 | if (NULL == my_identity) | ||
1214 | { | ||
1215 | GNUNET_break (0); | ||
1216 | return; | ||
1217 | } | ||
1218 | GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id)); | ||
1219 | } | ||
1220 | |||
1221 | |||
1222 | /** | ||
1223 | * Method called whenever a given peer connects. | ||
1224 | * | ||
1225 | * @param cls closure | ||
1226 | * @param peer peer identity this notification is about | ||
1227 | */ | ||
1228 | static void * | ||
1229 | core_connect_cb (void *cls, | ||
1230 | const struct GNUNET_PeerIdentity *peer, | ||
1231 | struct GNUNET_MQ_Handle *mq) | ||
1232 | { | ||
1233 | struct CadetPeer *cp; | ||
1234 | |||
1235 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1236 | "CORE connection to peer %s was established.\n", | ||
1237 | GNUNET_i2s (peer)); | ||
1238 | cp = GCP_get (peer, GNUNET_YES); | ||
1239 | GCP_set_mq (cp, mq); | ||
1240 | return cp; | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Method called whenever a peer disconnects. | ||
1246 | * | ||
1247 | * @param cls closure | ||
1248 | * @param peer peer identity this notification is about | ||
1249 | */ | ||
1250 | static void | ||
1251 | core_disconnect_cb (void *cls, | ||
1252 | const struct GNUNET_PeerIdentity *peer, | ||
1253 | void *peer_cls) | ||
1254 | { | ||
1255 | struct CadetPeer *cp = peer_cls; | ||
1256 | |||
1257 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1258 | "CORE connection to peer %s went down.\n", | ||
1259 | GNUNET_i2s (peer)); | ||
1260 | GCP_set_mq (cp, NULL); | ||
1261 | } | ||
1262 | |||
1263 | |||
1264 | /** | ||
1265 | * Initialize the CORE subsystem. | ||
1266 | * | ||
1267 | * @param c Configuration. | ||
1268 | */ | ||
1269 | void | ||
1270 | GCO_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1271 | { | ||
1272 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1273 | { GNUNET_MQ_hd_var_size (connection_create, | ||
1274 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
1275 | struct GNUNET_CADET_ConnectionCreateMessage, | ||
1276 | NULL), | ||
1277 | GNUNET_MQ_hd_fixed_size (connection_create_ack, | ||
1278 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
1279 | struct GNUNET_CADET_ConnectionCreateAckMessage, | ||
1280 | NULL), | ||
1281 | GNUNET_MQ_hd_fixed_size (connection_broken, | ||
1282 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
1283 | struct GNUNET_CADET_ConnectionBrokenMessage, | ||
1284 | NULL), | ||
1285 | GNUNET_MQ_hd_fixed_size (connection_destroy, | ||
1286 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
1287 | struct GNUNET_CADET_ConnectionDestroyMessage, | ||
1288 | NULL), | ||
1289 | GNUNET_MQ_hd_fixed_size (tunnel_kx, | ||
1290 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, | ||
1291 | struct GNUNET_CADET_TunnelKeyExchangeMessage, | ||
1292 | NULL), | ||
1293 | GNUNET_MQ_hd_fixed_size (tunnel_kx_auth, | ||
1294 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH, | ||
1295 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage, | ||
1296 | NULL), | ||
1297 | GNUNET_MQ_hd_var_size (tunnel_encrypted, | ||
1298 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, | ||
1299 | struct GNUNET_CADET_TunnelEncryptedMessage, | ||
1300 | NULL), | ||
1301 | GNUNET_MQ_handler_end () }; | ||
1302 | |||
1303 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1304 | "CADET", | ||
1305 | "MAX_ROUTES", | ||
1306 | &max_routes)) | ||
1307 | max_routes = 5000; | ||
1308 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1309 | "CADET", | ||
1310 | "MAX_MSGS_QUEUE", | ||
1311 | &max_buffers)) | ||
1312 | max_buffers = 10000; | ||
1313 | routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO); | ||
1314 | route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1315 | core = GNUNET_CORE_connect (c, | ||
1316 | NULL, | ||
1317 | &core_init_cb, | ||
1318 | &core_connect_cb, | ||
1319 | &core_disconnect_cb, | ||
1320 | handlers); | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Shut down the CORE subsystem. | ||
1326 | */ | ||
1327 | void | ||
1328 | GCO_shutdown () | ||
1329 | { | ||
1330 | if (NULL != core) | ||
1331 | { | ||
1332 | GNUNET_CORE_disconnect (core); | ||
1333 | core = NULL; | ||
1334 | } | ||
1335 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); | ||
1336 | GNUNET_CONTAINER_multishortmap_destroy (routes); | ||
1337 | routes = NULL; | ||
1338 | GNUNET_CONTAINER_heap_destroy (route_heap); | ||
1339 | route_heap = NULL; | ||
1340 | if (NULL != timeout_task) | ||
1341 | { | ||
1342 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
1343 | timeout_task = NULL; | ||
1344 | } | ||
1345 | } | ||
1346 | |||
1347 | |||
1348 | /* end of gnunet-cadet-service_core.c */ | ||