diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.c | 1093 |
1 files changed, 0 insertions, 1093 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c deleted file mode 100644 index 6976e66e4..000000000 --- a/src/cadet/gnunet-service-cadet-new_connection.c +++ /dev/null | |||
@@ -1,1093 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet-new_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-service-cadet-new.h" | ||
30 | #include "gnunet-service-cadet-new_channel.h" | ||
31 | #include "gnunet-service-cadet-new_connection.h" | ||
32 | #include "gnunet-service-cadet-new_paths.h" | ||
33 | #include "gnunet-service-cadet-new_peer.h" | ||
34 | #include "gnunet-service-cadet-new_tunnels.h" | ||
35 | #include "gnunet_cadet_service.h" | ||
36 | #include "gnunet_statistics_service.h" | ||
37 | #include "cadet_protocol.h" | ||
38 | |||
39 | |||
40 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__) | ||
41 | |||
42 | |||
43 | /** | ||
44 | * All the states a connection can be in. | ||
45 | */ | ||
46 | enum CadetConnectionState | ||
47 | { | ||
48 | /** | ||
49 | * Uninitialized status, we have not yet even gotten the message queue. | ||
50 | */ | ||
51 | CADET_CONNECTION_NEW, | ||
52 | |||
53 | /** | ||
54 | * Connection create message in queue, awaiting transmission by CORE. | ||
55 | */ | ||
56 | CADET_CONNECTION_SENDING_CREATE, | ||
57 | |||
58 | /** | ||
59 | * Connection create message sent, waiting for ACK. | ||
60 | */ | ||
61 | CADET_CONNECTION_SENT, | ||
62 | |||
63 | /** | ||
64 | * We are an inbound connection, and received a CREATE. Need to | ||
65 | * send an CREATE_ACK back. | ||
66 | */ | ||
67 | CADET_CONNECTION_CREATE_RECEIVED, | ||
68 | |||
69 | /** | ||
70 | * Connection confirmed, ready to carry traffic. | ||
71 | */ | ||
72 | CADET_CONNECTION_READY | ||
73 | |||
74 | }; | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Low-level connection to a destination. | ||
79 | */ | ||
80 | struct CadetConnection | ||
81 | { | ||
82 | |||
83 | /** | ||
84 | * ID of the connection. | ||
85 | */ | ||
86 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
87 | |||
88 | /** | ||
89 | * To which peer does this connection go? | ||
90 | */ | ||
91 | struct CadetPeer *destination; | ||
92 | |||
93 | /** | ||
94 | * Which tunnel is using this connection? | ||
95 | */ | ||
96 | struct CadetTConnection *ct; | ||
97 | |||
98 | /** | ||
99 | * Path we are using to our destination. | ||
100 | */ | ||
101 | struct CadetPeerPath *path; | ||
102 | |||
103 | /** | ||
104 | * Pending message, NULL if we are ready to transmit. | ||
105 | */ | ||
106 | struct GNUNET_MQ_Envelope *env; | ||
107 | |||
108 | /** | ||
109 | * Handle for calling #GCP_request_mq_cancel() once we are finished. | ||
110 | */ | ||
111 | struct GCP_MessageQueueManager *mq_man; | ||
112 | |||
113 | /** | ||
114 | * Task for connection maintenance. | ||
115 | */ | ||
116 | struct GNUNET_SCHEDULER_Task *task; | ||
117 | |||
118 | /** | ||
119 | * Queue entry for keepalive messages. | ||
120 | */ | ||
121 | struct CadetTunnelQueueEntry *keepalive_qe; | ||
122 | |||
123 | /** | ||
124 | * Function to call once we are ready to transmit. | ||
125 | */ | ||
126 | GCC_ReadyCallback ready_cb; | ||
127 | |||
128 | /** | ||
129 | * Closure for @e ready_cb. | ||
130 | */ | ||
131 | void *ready_cb_cls; | ||
132 | |||
133 | /** | ||
134 | * How long do we wait before we try again with a CREATE message? | ||
135 | */ | ||
136 | struct GNUNET_TIME_Relative retry_delay; | ||
137 | |||
138 | /** | ||
139 | * Performance metrics for this connection. | ||
140 | */ | ||
141 | struct CadetConnectionMetrics metrics; | ||
142 | |||
143 | /** | ||
144 | * State of the connection. | ||
145 | */ | ||
146 | enum CadetConnectionState state; | ||
147 | |||
148 | /** | ||
149 | * Options for the route, control buffering. | ||
150 | */ | ||
151 | enum GNUNET_CADET_ChannelOption options; | ||
152 | |||
153 | /** | ||
154 | * How many latency observations did we make for this connection? | ||
155 | */ | ||
156 | unsigned int latency_datapoints; | ||
157 | |||
158 | /** | ||
159 | * Offset of our @e destination in @e path. | ||
160 | */ | ||
161 | unsigned int off; | ||
162 | |||
163 | /** | ||
164 | * Are we ready to transmit via @e mq_man right now? | ||
165 | */ | ||
166 | int mqm_ready; | ||
167 | |||
168 | }; | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Lookup a connection by its identifier. | ||
173 | * | ||
174 | * @param cid identifier to resolve | ||
175 | * @return NULL if connection was not found | ||
176 | */ | ||
177 | struct CadetConnection * | ||
178 | GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
179 | { | ||
180 | return GNUNET_CONTAINER_multishortmap_get (connections, | ||
181 | &cid->connection_of_tunnel); | ||
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Update the connection state. Also triggers the necessary | ||
187 | * MQM notifications. | ||
188 | * | ||
189 | * @param cc connection to update the state for | ||
190 | * @param new_state new state for @a cc | ||
191 | * @param new_mqm_ready new `mqm_ready` state for @a cc | ||
192 | */ | ||
193 | static void | ||
194 | update_state (struct CadetConnection *cc, | ||
195 | enum CadetConnectionState new_state, | ||
196 | int new_mqm_ready) | ||
197 | { | ||
198 | int old_ready; | ||
199 | int new_ready; | ||
200 | |||
201 | if ( (new_state == cc->state) && | ||
202 | (new_mqm_ready == cc->mqm_ready) ) | ||
203 | return; /* no change, nothing to do */ | ||
204 | old_ready = ( (CADET_CONNECTION_READY == cc->state) && | ||
205 | (GNUNET_YES == cc->mqm_ready) ); | ||
206 | new_ready = ( (CADET_CONNECTION_READY == new_state) && | ||
207 | (GNUNET_YES == new_mqm_ready) ); | ||
208 | cc->state = new_state; | ||
209 | cc->mqm_ready = new_mqm_ready; | ||
210 | if (old_ready != new_ready) | ||
211 | cc->ready_cb (cc->ready_cb_cls, | ||
212 | new_ready); | ||
213 | } | ||
214 | |||
215 | |||
216 | /** | ||
217 | * Destroy a connection, part of the internal implementation. Called | ||
218 | * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel(). | ||
219 | * | ||
220 | * @param cc connection to destroy | ||
221 | */ | ||
222 | static void | ||
223 | GCC_destroy (struct CadetConnection *cc) | ||
224 | { | ||
225 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
226 | "Destroying %s\n", | ||
227 | GCC_2s (cc)); | ||
228 | if (NULL != cc->mq_man) | ||
229 | { | ||
230 | GCP_request_mq_cancel (cc->mq_man, | ||
231 | NULL); | ||
232 | cc->mq_man = NULL; | ||
233 | } | ||
234 | if (NULL != cc->task) | ||
235 | { | ||
236 | GNUNET_SCHEDULER_cancel (cc->task); | ||
237 | cc->task = NULL; | ||
238 | } | ||
239 | if (NULL != cc->keepalive_qe) | ||
240 | { | ||
241 | GCT_send_cancel (cc->keepalive_qe); | ||
242 | cc->keepalive_qe = NULL; | ||
243 | } | ||
244 | GCPP_del_connection (cc->path, | ||
245 | cc->off, | ||
246 | cc); | ||
247 | for (unsigned int i=0;i<cc->off;i++) | ||
248 | GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, | ||
249 | i), | ||
250 | cc); | ||
251 | GNUNET_assert (GNUNET_YES == | ||
252 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
253 | &GCC_get_id (cc)->connection_of_tunnel, | ||
254 | cc)); | ||
255 | GNUNET_free (cc); | ||
256 | } | ||
257 | |||
258 | |||
259 | |||
260 | /** | ||
261 | * Destroy a connection, called when the CORE layer is already done | ||
262 | * (i.e. has received a BROKEN message), but if we still have to | ||
263 | * communicate the destruction of the connection to the tunnel (if one | ||
264 | * exists). | ||
265 | * | ||
266 | * @param cc connection to destroy | ||
267 | */ | ||
268 | void | ||
269 | GCC_destroy_without_core (struct CadetConnection *cc) | ||
270 | { | ||
271 | if (NULL != cc->ct) | ||
272 | { | ||
273 | GCT_connection_lost (cc->ct); | ||
274 | cc->ct = NULL; | ||
275 | } | ||
276 | GCC_destroy (cc); | ||
277 | } | ||
278 | |||
279 | |||
280 | /** | ||
281 | * Destroy a connection, called if the tunnel association with the | ||
282 | * connection was already broken, but we still need to notify the CORE | ||
283 | * layer about the breakage. | ||
284 | * | ||
285 | * @param cc connection to destroy | ||
286 | */ | ||
287 | void | ||
288 | GCC_destroy_without_tunnel (struct CadetConnection *cc) | ||
289 | { | ||
290 | cc->ct = NULL; | ||
291 | if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) && | ||
292 | (NULL != cc->mq_man) ) | ||
293 | { | ||
294 | struct GNUNET_MQ_Envelope *env; | ||
295 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | ||
296 | |||
297 | /* Need to notify next hop that we are down. */ | ||
298 | env = GNUNET_MQ_msg (destroy_msg, | ||
299 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
300 | destroy_msg->cid = cc->cid; | ||
301 | GCP_request_mq_cancel (cc->mq_man, | ||
302 | env); | ||
303 | cc->mq_man = NULL; | ||
304 | } | ||
305 | GCC_destroy (cc); | ||
306 | } | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Return the tunnel associated with this connection. | ||
311 | * | ||
312 | * @param cc connection to query | ||
313 | * @return corresponding entry in the tunnel's connection list | ||
314 | */ | ||
315 | struct CadetTConnection * | ||
316 | GCC_get_ct (struct CadetConnection *cc) | ||
317 | { | ||
318 | return cc->ct; | ||
319 | } | ||
320 | |||
321 | |||
322 | /** | ||
323 | * Obtain performance @a metrics from @a cc. | ||
324 | * | ||
325 | * @param cc connection to query | ||
326 | * @return the metrics | ||
327 | */ | ||
328 | const struct CadetConnectionMetrics * | ||
329 | GCC_get_metrics (struct CadetConnection *cc) | ||
330 | { | ||
331 | return &cc->metrics; | ||
332 | } | ||
333 | |||
334 | |||
335 | /** | ||
336 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the | ||
337 | * tunnel to prevent it from timing out. | ||
338 | * | ||
339 | * @param cls the `struct CadetConnection` to keep alive. | ||
340 | */ | ||
341 | static void | ||
342 | send_keepalive (void *cls); | ||
343 | |||
344 | |||
345 | /** | ||
346 | * Keepalive was transmitted. Remember this, and possibly | ||
347 | * schedule the next one. | ||
348 | * | ||
349 | * @param cls the `struct CadetConnection` to keep alive. | ||
350 | * @param cid identifier of the connection within the tunnel, NULL | ||
351 | * if transmission failed | ||
352 | */ | ||
353 | static void | ||
354 | keepalive_done (void *cls, | ||
355 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
356 | { | ||
357 | struct CadetConnection *cc = cls; | ||
358 | |||
359 | cc->keepalive_qe = NULL; | ||
360 | if ( (GNUNET_YES == cc->mqm_ready) && | ||
361 | (NULL == cc->task) ) | ||
362 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
363 | &send_keepalive, | ||
364 | cc); | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the | ||
370 | * tunnel to prevent it from timing out. | ||
371 | * | ||
372 | * @param cls the `struct CadetConnection` to keep alive. | ||
373 | */ | ||
374 | static void | ||
375 | send_keepalive (void *cls) | ||
376 | { | ||
377 | struct CadetConnection *cc = cls; | ||
378 | struct GNUNET_MessageHeader msg; | ||
379 | |||
380 | cc->task = NULL; | ||
381 | if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t)) | ||
382 | { | ||
383 | /* Tunnel not yet ready, wait with keepalives... */ | ||
384 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
385 | &send_keepalive, | ||
386 | cc); | ||
387 | return; | ||
388 | } | ||
389 | GNUNET_assert (NULL != cc->ct); | ||
390 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
391 | GNUNET_assert (NULL == cc->keepalive_qe); | ||
392 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
393 | "Sending KEEPALIVE on behalf of %s via %s\n", | ||
394 | GCC_2s (cc), | ||
395 | GCT_2s (cc->ct->t)); | ||
396 | GNUNET_STATISTICS_update (stats, | ||
397 | "# keepalives sent", | ||
398 | 1, | ||
399 | GNUNET_NO); | ||
400 | msg.size = htons (sizeof (msg)); | ||
401 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE); | ||
402 | |||
403 | cc->keepalive_qe | ||
404 | = GCT_send (cc->ct->t, | ||
405 | &msg, | ||
406 | &keepalive_done, | ||
407 | cc); | ||
408 | } | ||
409 | |||
410 | |||
411 | /** | ||
412 | * We sent a message for which we expect to receive an ACK via | ||
413 | * the connection identified by @a cti. | ||
414 | * | ||
415 | * @param cid connection identifier where we expect an ACK | ||
416 | */ | ||
417 | void | ||
418 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
419 | { | ||
420 | struct CadetConnection *cc; | ||
421 | |||
422 | cc = GCC_lookup (cid); | ||
423 | if (NULL == cc) | ||
424 | return; /* whopise, connection alredy down? */ | ||
425 | cc->metrics.num_acked_transmissions++; | ||
426 | } | ||
427 | |||
428 | |||
429 | /** | ||
430 | * We observed an ACK for a message that was originally sent via | ||
431 | * the connection identified by @a cti. | ||
432 | * | ||
433 | * @param cti connection identifier where we got an ACK for a message | ||
434 | * that was originally sent via this connection (the ACK | ||
435 | * may have gotten back to us via a different connection). | ||
436 | */ | ||
437 | void | ||
438 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
439 | { | ||
440 | struct CadetConnection *cc; | ||
441 | |||
442 | cc = GCC_lookup (cid); | ||
443 | if (NULL == cc) | ||
444 | return; /* whopise, connection alredy down? */ | ||
445 | cc->metrics.num_successes++; | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * We observed some the given @a latency on the connection | ||
451 | * identified by @a cti. (The same connection was taken | ||
452 | * in both directions.) | ||
453 | * | ||
454 | * @param cid connection identifier where we measured latency | ||
455 | * @param latency the observed latency | ||
456 | */ | ||
457 | void | ||
458 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
459 | struct GNUNET_TIME_Relative latency) | ||
460 | { | ||
461 | struct CadetConnection *cc; | ||
462 | double weight; | ||
463 | double result; | ||
464 | |||
465 | cc = GCC_lookup (cid); | ||
466 | if (NULL == cc) | ||
467 | return; /* whopise, connection alredy down? */ | ||
468 | GNUNET_STATISTICS_update (stats, | ||
469 | "# latencies observed", | ||
470 | 1, | ||
471 | GNUNET_NO); | ||
472 | cc->latency_datapoints++; | ||
473 | if (cc->latency_datapoints >= 7) | ||
474 | weight = 7.0; | ||
475 | else | ||
476 | weight = cc->latency_datapoints; | ||
477 | /* Compute weighted average, giving at MOST weight 7 to the | ||
478 | existing values, or less if that value is based on fewer than 7 | ||
479 | measurements. */ | ||
480 | result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us; | ||
481 | result /= (weight + 1.0); | ||
482 | cc->metrics.aged_latency.rel_value_us = (uint64_t) result; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying | ||
488 | * that the end-to-end connection is up. Process it. | ||
489 | * | ||
490 | * @param cc the connection that got the ACK. | ||
491 | */ | ||
492 | void | ||
493 | GCC_handle_connection_create_ack (struct CadetConnection *cc) | ||
494 | { | ||
495 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
496 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", | ||
497 | GCC_2s (cc), | ||
498 | cc->state, | ||
499 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
500 | if (CADET_CONNECTION_READY == cc->state) | ||
501 | return; /* Duplicate ACK, ignore */ | ||
502 | if (NULL != cc->task) | ||
503 | { | ||
504 | GNUNET_SCHEDULER_cancel (cc->task); | ||
505 | cc->task = NULL; | ||
506 | } | ||
507 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
508 | update_state (cc, | ||
509 | CADET_CONNECTION_READY, | ||
510 | cc->mqm_ready); | ||
511 | if ( (NULL == cc->keepalive_qe) && | ||
512 | (GNUNET_YES == cc->mqm_ready) && | ||
513 | (NULL == cc->task) ) | ||
514 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
515 | &send_keepalive, | ||
516 | cc); | ||
517 | } | ||
518 | |||
519 | |||
520 | /** | ||
521 | * Handle KX message. | ||
522 | * | ||
523 | * @param cc connection that received encrypted message | ||
524 | * @param msg the key exchange message | ||
525 | */ | ||
526 | void | ||
527 | GCC_handle_kx (struct CadetConnection *cc, | ||
528 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
529 | { | ||
530 | if (CADET_CONNECTION_SENT == cc->state) | ||
531 | { | ||
532 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
533 | clearly something is working, so pretend we got an ACK. */ | ||
534 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
535 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
536 | GCC_2s (cc)); | ||
537 | GCC_handle_connection_create_ack (cc); | ||
538 | } | ||
539 | GCT_handle_kx (cc->ct, | ||
540 | msg); | ||
541 | } | ||
542 | |||
543 | |||
544 | /** | ||
545 | * Handle KX_AUTH message. | ||
546 | * | ||
547 | * @param cc connection that received encrypted message | ||
548 | * @param msg the key exchange message | ||
549 | */ | ||
550 | void | ||
551 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
552 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
553 | { | ||
554 | if (CADET_CONNECTION_SENT == cc->state) | ||
555 | { | ||
556 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
557 | clearly something is working, so pretend we got an ACK. */ | ||
558 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
559 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
560 | GCC_2s (cc)); | ||
561 | GCC_handle_connection_create_ack (cc); | ||
562 | } | ||
563 | GCT_handle_kx_auth (cc->ct, | ||
564 | msg); | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Handle encrypted message. | ||
570 | * | ||
571 | * @param cc connection that received encrypted message | ||
572 | * @param msg the encrypted message to decrypt | ||
573 | */ | ||
574 | void | ||
575 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
576 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
577 | { | ||
578 | if (CADET_CONNECTION_SENT == cc->state) | ||
579 | { | ||
580 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
581 | clearly something is working, so pretend we got an ACK. */ | ||
582 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
583 | "Faking connection ACK for %s due to ENCRYPTED payload\n", | ||
584 | GCC_2s (cc)); | ||
585 | GCC_handle_connection_create_ack (cc); | ||
586 | } | ||
587 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
588 | GCT_handle_encrypted (cc->ct, | ||
589 | msg); | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the | ||
595 | * first hop. | ||
596 | * | ||
597 | * @param cls the `struct CadetConnection` to initiate | ||
598 | */ | ||
599 | static void | ||
600 | send_create (void *cls) | ||
601 | { | ||
602 | struct CadetConnection *cc = cls; | ||
603 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
604 | struct GNUNET_PeerIdentity *pids; | ||
605 | struct GNUNET_MQ_Envelope *env; | ||
606 | unsigned int path_length; | ||
607 | |||
608 | cc->task = NULL; | ||
609 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
610 | path_length = GCPP_get_length (cc->path); | ||
611 | env = GNUNET_MQ_msg_extra (create_msg, | ||
612 | (1 + path_length) * sizeof (struct GNUNET_PeerIdentity), | ||
613 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
614 | create_msg->options = htonl ((uint32_t) cc->options); | ||
615 | create_msg->cid = cc->cid; | ||
616 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
617 | pids[0] = my_full_id; | ||
618 | for (unsigned int i=0;i<path_length;i++) | ||
619 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | ||
620 | i)); | ||
621 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
622 | "Sending CADET_CONNECTION_CREATE message for %s\n", | ||
623 | GCC_2s (cc)); | ||
624 | cc->env = env; | ||
625 | update_state (cc, | ||
626 | CADET_CONNECTION_SENT, | ||
627 | GNUNET_NO); | ||
628 | GCP_send (cc->mq_man, | ||
629 | env); | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * Send a CREATE_ACK message towards the origin. | ||
635 | * | ||
636 | * @param cls the `struct CadetConnection` to initiate | ||
637 | */ | ||
638 | static void | ||
639 | send_create_ack (void *cls) | ||
640 | { | ||
641 | struct CadetConnection *cc = cls; | ||
642 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; | ||
643 | struct GNUNET_MQ_Envelope *env; | ||
644 | |||
645 | cc->task = NULL; | ||
646 | GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state); | ||
647 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
648 | "Sending CONNECTION_CREATE_ACK message for %s\n", | ||
649 | GCC_2s (cc)); | ||
650 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
651 | env = GNUNET_MQ_msg (ack_msg, | ||
652 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); | ||
653 | ack_msg->cid = cc->cid; | ||
654 | cc->env = env; | ||
655 | update_state (cc, | ||
656 | CADET_CONNECTION_READY, | ||
657 | GNUNET_NO); | ||
658 | GCP_send (cc->mq_man, | ||
659 | env); | ||
660 | } | ||
661 | |||
662 | |||
663 | /** | ||
664 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
665 | * connection that we already have. Either our ACK got lost | ||
666 | * or something is fishy. Consider retransmitting the ACK. | ||
667 | * | ||
668 | * @param cc connection that got the duplicate CREATE | ||
669 | */ | ||
670 | void | ||
671 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
672 | { | ||
673 | if (GNUNET_YES == cc->mqm_ready) | ||
674 | { | ||
675 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
676 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", | ||
677 | GCC_2s (cc), | ||
678 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
679 | /* Revert back to the state of having only received the 'CREATE', | ||
680 | and immediately proceed to send the CREATE_ACK. */ | ||
681 | update_state (cc, | ||
682 | CADET_CONNECTION_CREATE_RECEIVED, | ||
683 | cc->mqm_ready); | ||
684 | if (NULL != cc->task) | ||
685 | GNUNET_SCHEDULER_cancel (cc->task); | ||
686 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
687 | cc); | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | /* We are currently sending something else back, which | ||
692 | can only be an ACK or payload, either of which would | ||
693 | do. So actually no need to do anything. */ | ||
694 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
695 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", | ||
696 | GCC_2s (cc)); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | |||
701 | /** | ||
702 | * There has been a change in the message queue existence for our | ||
703 | * peer at the first hop. Adjust accordingly. | ||
704 | * | ||
705 | * @param cls the `struct CadetConnection` | ||
706 | * @param available #GNUNET_YES if sending is now possible, | ||
707 | * #GNUNET_NO if sending is no longer possible | ||
708 | * #GNUNET_SYSERR if sending is no longer possible | ||
709 | * and the last envelope was discarded | ||
710 | */ | ||
711 | static void | ||
712 | manage_first_hop_mq (void *cls, | ||
713 | int available) | ||
714 | { | ||
715 | struct CadetConnection *cc = cls; | ||
716 | |||
717 | if (GNUNET_YES != available) | ||
718 | { | ||
719 | /* Connection is down, for now... */ | ||
720 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
721 | "Core MQ for %s went down\n", | ||
722 | GCC_2s (cc)); | ||
723 | update_state (cc, | ||
724 | CADET_CONNECTION_NEW, | ||
725 | GNUNET_NO); | ||
726 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
727 | if (NULL != cc->task) | ||
728 | { | ||
729 | GNUNET_SCHEDULER_cancel (cc->task); | ||
730 | cc->task = NULL; | ||
731 | } | ||
732 | return; | ||
733 | } | ||
734 | |||
735 | update_state (cc, | ||
736 | cc->state, | ||
737 | GNUNET_YES); | ||
738 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
739 | "Core MQ for %s became available in state %d\n", | ||
740 | GCC_2s (cc), | ||
741 | cc->state); | ||
742 | switch (cc->state) | ||
743 | { | ||
744 | case CADET_CONNECTION_NEW: | ||
745 | /* Transmit immediately */ | ||
746 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | ||
747 | cc); | ||
748 | break; | ||
749 | case CADET_CONNECTION_SENDING_CREATE: | ||
750 | /* Should not be possible to be called in this state. */ | ||
751 | GNUNET_assert (0); | ||
752 | break; | ||
753 | case CADET_CONNECTION_SENT: | ||
754 | /* Retry a bit later... */ | ||
755 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
756 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
757 | &send_create, | ||
758 | cc); | ||
759 | break; | ||
760 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
761 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
762 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
763 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
764 | cc); | ||
765 | break; | ||
766 | case CADET_CONNECTION_READY: | ||
767 | if ( (NULL == cc->keepalive_qe) && | ||
768 | (GNUNET_YES == cc->mqm_ready) && | ||
769 | (NULL == cc->task) ) | ||
770 | { | ||
771 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
772 | "Scheduling keepalive for %s in %s\n", | ||
773 | GCC_2s (cc), | ||
774 | GNUNET_STRINGS_relative_time_to_string (keepalive_period, | ||
775 | GNUNET_YES)); | ||
776 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
777 | &send_keepalive, | ||
778 | cc); | ||
779 | } | ||
780 | break; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | ||
786 | * Create a connection to @a destination via @a path and notify @a cb | ||
787 | * whenever we are ready for more data. Shared logic independent of | ||
788 | * who is initiating the connection. | ||
789 | * | ||
790 | * @param destination where to go | ||
791 | * @param path which path to take (may not be the full path) | ||
792 | * @param off offset of @a destination on @a path | ||
793 | * @param options options for the connection | ||
794 | * @param ct which tunnel uses this connection | ||
795 | * @param init_state initial state for the connection | ||
796 | * @param ready_cb function to call when ready to transmit | ||
797 | * @param ready_cb_cls closure for @a cb | ||
798 | * @return handle to the connection | ||
799 | */ | ||
800 | static struct CadetConnection * | ||
801 | connection_create (struct CadetPeer *destination, | ||
802 | struct CadetPeerPath *path, | ||
803 | unsigned int off, | ||
804 | enum GNUNET_CADET_ChannelOption options, | ||
805 | struct CadetTConnection *ct, | ||
806 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
807 | enum CadetConnectionState init_state, | ||
808 | GCC_ReadyCallback ready_cb, | ||
809 | void *ready_cb_cls) | ||
810 | { | ||
811 | struct CadetConnection *cc; | ||
812 | struct CadetPeer *first_hop; | ||
813 | |||
814 | cc = GNUNET_new (struct CadetConnection); | ||
815 | cc->options = options; | ||
816 | cc->state = init_state; | ||
817 | cc->ct = ct; | ||
818 | cc->cid = *cid; | ||
819 | GNUNET_assert (GNUNET_OK == | ||
820 | GNUNET_CONTAINER_multishortmap_put (connections, | ||
821 | &GCC_get_id (cc)->connection_of_tunnel, | ||
822 | cc, | ||
823 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
824 | cc->ready_cb = ready_cb; | ||
825 | cc->ready_cb_cls = ready_cb_cls; | ||
826 | cc->path = path; | ||
827 | cc->off = off; | ||
828 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
829 | "Creating %s using path %s\n", | ||
830 | GCC_2s (cc), | ||
831 | GCPP_2s (path)); | ||
832 | GCPP_add_connection (path, | ||
833 | off, | ||
834 | cc); | ||
835 | for (unsigned int i=0;i<off;i++) | ||
836 | GCP_add_connection (GCPP_get_peer_at_offset (path, | ||
837 | i), | ||
838 | cc); | ||
839 | |||
840 | first_hop = GCPP_get_peer_at_offset (path, | ||
841 | 0); | ||
842 | cc->mq_man = GCP_request_mq (first_hop, | ||
843 | &manage_first_hop_mq, | ||
844 | cc); | ||
845 | return cc; | ||
846 | } | ||
847 | |||
848 | |||
849 | /** | ||
850 | * Create a connection to @a destination via @a path and | ||
851 | * notify @a cb whenever we are ready for more data. This | ||
852 | * is an inbound tunnel, so we must use the existing @a cid | ||
853 | * | ||
854 | * @param destination where to go | ||
855 | * @param path which path to take (may not be the full path) | ||
856 | * @param options options for the connection | ||
857 | * @param ct which tunnel uses this connection | ||
858 | * @param ready_cb function to call when ready to transmit | ||
859 | * @param ready_cb_cls closure for @a cb | ||
860 | * @return handle to the connection, NULL if we already have | ||
861 | * a connection that takes precedence on @a path | ||
862 | */ | ||
863 | struct CadetConnection * | ||
864 | GCC_create_inbound (struct CadetPeer *destination, | ||
865 | struct CadetPeerPath *path, | ||
866 | enum GNUNET_CADET_ChannelOption options, | ||
867 | struct CadetTConnection *ct, | ||
868 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
869 | GCC_ReadyCallback ready_cb, | ||
870 | void *ready_cb_cls) | ||
871 | { | ||
872 | struct CadetConnection *cc; | ||
873 | unsigned int off; | ||
874 | |||
875 | off = GCPP_find_peer (path, | ||
876 | destination); | ||
877 | GNUNET_assert (UINT_MAX != off); | ||
878 | cc = GCPP_get_connection (path, | ||
879 | destination, | ||
880 | off); | ||
881 | if (NULL != cc) | ||
882 | { | ||
883 | int cmp; | ||
884 | |||
885 | cmp = memcmp (cid, | ||
886 | &cc->cid, | ||
887 | sizeof (*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 | options, | ||
924 | ct, | ||
925 | cid, | ||
926 | CADET_CONNECTION_CREATE_RECEIVED, | ||
927 | ready_cb, | ||
928 | ready_cb_cls); | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Create a connection to @a destination via @a path and | ||
934 | * notify @a cb whenever we are ready for more data. | ||
935 | * | ||
936 | * @param destination where to go | ||
937 | * @param path which path to take (may not be the full path) | ||
938 | * @param off offset of @a destination on @a path | ||
939 | * @param options options for the connection | ||
940 | * @param ct tunnel that uses the connection | ||
941 | * @param ready_cb function to call when ready to transmit | ||
942 | * @param ready_cb_cls closure for @a cb | ||
943 | * @return handle to the connection | ||
944 | */ | ||
945 | struct CadetConnection * | ||
946 | GCC_create (struct CadetPeer *destination, | ||
947 | struct CadetPeerPath *path, | ||
948 | unsigned int off, | ||
949 | enum GNUNET_CADET_ChannelOption options, | ||
950 | struct CadetTConnection *ct, | ||
951 | GCC_ReadyCallback ready_cb, | ||
952 | void *ready_cb_cls) | ||
953 | { | ||
954 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
955 | |||
956 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
957 | &cid, | ||
958 | sizeof (cid)); | ||
959 | return connection_create (destination, | ||
960 | path, | ||
961 | off, | ||
962 | options, | ||
963 | ct, | ||
964 | &cid, | ||
965 | CADET_CONNECTION_NEW, | ||
966 | ready_cb, | ||
967 | ready_cb_cls); | ||
968 | } | ||
969 | |||
970 | |||
971 | /** | ||
972 | * Transmit message @a msg via connection @a cc. Must only be called | ||
973 | * (once) after the connection has signalled that it is ready via the | ||
974 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
975 | * connection is right now ready for transmission. | ||
976 | * | ||
977 | * @param cc connection identification | ||
978 | * @param env envelope with message to transmit; must NOT | ||
979 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
980 | */ | ||
981 | void | ||
982 | GCC_transmit (struct CadetConnection *cc, | ||
983 | struct GNUNET_MQ_Envelope *env) | ||
984 | { | ||
985 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
986 | "Scheduling message for transmission on %s\n", | ||
987 | GCC_2s (cc)); | ||
988 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
989 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); | ||
990 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
991 | cc->mqm_ready = GNUNET_NO; | ||
992 | if (NULL != cc->task) | ||
993 | { | ||
994 | GNUNET_SCHEDULER_cancel (cc->task); | ||
995 | cc->task = NULL; | ||
996 | } | ||
997 | GCP_send (cc->mq_man, | ||
998 | env); | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | /** | ||
1003 | * Obtain the path used by this connection. | ||
1004 | * | ||
1005 | * @param cc connection | ||
1006 | * @return path to @a cc | ||
1007 | */ | ||
1008 | struct CadetPeerPath * | ||
1009 | GCC_get_path (struct CadetConnection *cc) | ||
1010 | { | ||
1011 | return cc->path; | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | /** | ||
1016 | * Obtain unique ID for the connection. | ||
1017 | * | ||
1018 | * @param cc connection. | ||
1019 | * @return unique number of the connection | ||
1020 | */ | ||
1021 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
1022 | GCC_get_id (struct CadetConnection *cc) | ||
1023 | { | ||
1024 | return &cc->cid; | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | /** | ||
1029 | * Get a (static) string for a connection. | ||
1030 | * | ||
1031 | * @param cc Connection. | ||
1032 | */ | ||
1033 | const char * | ||
1034 | GCC_2s (const struct CadetConnection *cc) | ||
1035 | { | ||
1036 | static char buf[128]; | ||
1037 | |||
1038 | if (NULL == cc) | ||
1039 | return "Connection(NULL)"; | ||
1040 | |||
1041 | if (NULL != cc->ct) | ||
1042 | { | ||
1043 | GNUNET_snprintf (buf, | ||
1044 | sizeof (buf), | ||
1045 | "Connection %s (%s)", | ||
1046 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
1047 | GCT_2s (cc->ct->t)); | ||
1048 | return buf; | ||
1049 | } | ||
1050 | GNUNET_snprintf (buf, | ||
1051 | sizeof (buf), | ||
1052 | "Connection %s", | ||
1053 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
1054 | return buf; | ||
1055 | } | ||
1056 | |||
1057 | |||
1058 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
1059 | |||
1060 | |||
1061 | /** | ||
1062 | * Log connection info. | ||
1063 | * | ||
1064 | * @param cc connection | ||
1065 | * @param level Debug level to use. | ||
1066 | */ | ||
1067 | void | ||
1068 | GCC_debug (struct CadetConnection *cc, | ||
1069 | enum GNUNET_ErrorType level) | ||
1070 | { | ||
1071 | int do_log; | ||
1072 | |||
1073 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1074 | "cadet-con", | ||
1075 | __FILE__, __FUNCTION__, __LINE__); | ||
1076 | if (0 == do_log) | ||
1077 | return; | ||
1078 | if (NULL == cc) | ||
1079 | { | ||
1080 | LOG2 (level, | ||
1081 | "Connection (NULL)\n"); | ||
1082 | return; | ||
1083 | } | ||
1084 | LOG2 (level, | ||
1085 | "%s to %s via path %s in state %d is %s\n", | ||
1086 | GCC_2s (cc), | ||
1087 | GCP_2s (cc->destination), | ||
1088 | GCPP_2s (cc->path), | ||
1089 | cc->state, | ||
1090 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
1091 | } | ||
1092 | |||
1093 | /* end of gnunet-service-cadet-new_connection.c */ | ||