diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.c | 665 |
1 files changed, 665 insertions, 0 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c new file mode 100644 index 000000000..bf88d78e1 --- /dev/null +++ b/src/cadet/gnunet-service-cadet-new_connection.c | |||
@@ -0,0 +1,665 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file cadet/gnunet-service-cadet-new_connection.c | ||
24 | * @brief management of CORE-level end-to-end connections; establishes | ||
25 | * end-to-end routes and transmits messages along the route | ||
26 | * @author Bartlomiej Polot | ||
27 | * @author Christian Grothoff | ||
28 | * | ||
29 | * TODO: | ||
30 | * - keepalive messages | ||
31 | * - keep performance metrics (?) | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet-service-cadet-new_channel.h" | ||
35 | #include "gnunet-service-cadet-new_connection.h" | ||
36 | #include "gnunet-service-cadet-new_paths.h" | ||
37 | #include "gnunet-service-cadet-new_peer.h" | ||
38 | #include "gnunet-service-cadet-new_tunnels.h" | ||
39 | #include "gnunet_cadet_service.h" | ||
40 | #include "cadet_protocol.h" | ||
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 | * Function to call once we are ready to transmit. | ||
120 | */ | ||
121 | GCC_ReadyCallback ready_cb; | ||
122 | |||
123 | /** | ||
124 | * Closure for @e ready_cb. | ||
125 | */ | ||
126 | void *ready_cb_cls; | ||
127 | |||
128 | /** | ||
129 | * How long do we wait before we try again with a CREATE message? | ||
130 | */ | ||
131 | struct GNUNET_TIME_Relative retry_delay; | ||
132 | |||
133 | /** | ||
134 | * State of the connection. | ||
135 | */ | ||
136 | enum CadetConnectionState state; | ||
137 | |||
138 | /** | ||
139 | * Offset of our @e destination in @e path. | ||
140 | */ | ||
141 | unsigned int off; | ||
142 | |||
143 | /** | ||
144 | * Are we ready to transmit via @e mq_man right now? | ||
145 | */ | ||
146 | int mqm_ready; | ||
147 | |||
148 | }; | ||
149 | |||
150 | |||
151 | /** | ||
152 | * Destroy a connection. | ||
153 | * | ||
154 | * @param cc connection to destroy | ||
155 | */ | ||
156 | void | ||
157 | GCC_destroy (struct CadetConnection *cc) | ||
158 | { | ||
159 | struct GNUNET_MQ_Envelope *env = NULL; | ||
160 | |||
161 | if (CADET_CONNECTION_SENDING_CREATE != cc->state) | ||
162 | { | ||
163 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | ||
164 | |||
165 | /* Need to notify next hop that we are down. */ | ||
166 | env = GNUNET_MQ_msg (destroy_msg, | ||
167 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
168 | destroy_msg->cid = cc->cid; | ||
169 | } | ||
170 | GCP_request_mq_cancel (cc->mq_man, | ||
171 | env); | ||
172 | cc->mq_man = NULL; | ||
173 | GCPP_del_connection (cc->path, | ||
174 | cc->off, | ||
175 | cc); | ||
176 | GNUNET_assert (GNUNET_YES == | ||
177 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
178 | &GCC_get_id (cc)->connection_of_tunnel, | ||
179 | cc)); | ||
180 | GNUNET_free (cc); | ||
181 | } | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Return the tunnel associated with this connection. | ||
186 | * | ||
187 | * @param cc connection to query | ||
188 | * @return corresponding entry in the tunnel's connection list | ||
189 | */ | ||
190 | struct CadetTConnection * | ||
191 | GCC_get_ct (struct CadetConnection *cc) | ||
192 | { | ||
193 | return cc->ct; | ||
194 | } | ||
195 | |||
196 | |||
197 | /** | ||
198 | * A connection ACK was received for this connection, implying | ||
199 | * that the end-to-end connection is up. Process it. | ||
200 | * | ||
201 | * @param cc the connection that got the ACK. | ||
202 | */ | ||
203 | void | ||
204 | GCC_handle_connection_ack (struct CadetConnection *cc) | ||
205 | { | ||
206 | if (NULL != cc->task) | ||
207 | { | ||
208 | GNUNET_SCHEDULER_cancel (cc->task); | ||
209 | cc->task = NULL; | ||
210 | } | ||
211 | #if FIXME_KEEPALIVE | ||
212 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period, | ||
213 | &send_keepalive, | ||
214 | cc); | ||
215 | #endif | ||
216 | cc->state = CADET_CONNECTION_READY; | ||
217 | if (GNUNET_YES == cc->mqm_ready) | ||
218 | cc->ready_cb (cc->ready_cb_cls, | ||
219 | GNUNET_YES); | ||
220 | } | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Handle KX message. | ||
225 | * | ||
226 | * @param cc connection that received encrypted message | ||
227 | * @param msg the key exchange message | ||
228 | */ | ||
229 | void | ||
230 | GCC_handle_kx (struct CadetConnection *cc, | ||
231 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
232 | { | ||
233 | if (CADET_CONNECTION_SENT == cc->state) | ||
234 | { | ||
235 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
236 | clearly something is working, so pretend we got an ACK. */ | ||
237 | GCC_handle_connection_ack (cc); | ||
238 | } | ||
239 | GCT_handle_kx (cc->ct, | ||
240 | msg); | ||
241 | } | ||
242 | |||
243 | |||
244 | /** | ||
245 | * Handle encrypted message. | ||
246 | * | ||
247 | * @param cc connection that received encrypted message | ||
248 | * @param msg the encrypted message to decrypt | ||
249 | */ | ||
250 | void | ||
251 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
252 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
253 | { | ||
254 | if (CADET_CONNECTION_SENT == cc->state) | ||
255 | { | ||
256 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
257 | clearly something is working, so pretend we got an ACK. */ | ||
258 | GCC_handle_connection_ack (cc); | ||
259 | } | ||
260 | GCT_handle_encrypted (cc->ct, | ||
261 | msg); | ||
262 | } | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Send a CREATE message to the first hop. | ||
267 | * | ||
268 | * @param cls the `struct CadetConnection` to initiate | ||
269 | */ | ||
270 | static void | ||
271 | send_create (void *cls) | ||
272 | { | ||
273 | struct CadetConnection *cc = cls; | ||
274 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
275 | struct GNUNET_PeerIdentity *pids; | ||
276 | struct GNUNET_MQ_Envelope *env; | ||
277 | unsigned int path_length; | ||
278 | |||
279 | cc->task = NULL; | ||
280 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
281 | path_length = GCPP_get_length (cc->path); | ||
282 | env = GNUNET_MQ_msg_extra (create_msg, | ||
283 | path_length * sizeof (struct GNUNET_PeerIdentity), | ||
284 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
285 | create_msg->cid = cc->cid; | ||
286 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
287 | for (unsigned int i=0;i<path_length;i++) | ||
288 | pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | ||
289 | i)); | ||
290 | cc->env = env; | ||
291 | cc->mqm_ready = GNUNET_NO; | ||
292 | cc->state = CADET_CONNECTION_SENT; | ||
293 | GCP_send (cc->mq_man, | ||
294 | env); | ||
295 | } | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Send a CREATE_ACK message towards the origin. | ||
300 | * | ||
301 | * @param cls the `struct CadetConnection` to initiate | ||
302 | */ | ||
303 | static void | ||
304 | send_create_ack (void *cls) | ||
305 | { | ||
306 | struct CadetConnection *cc = cls; | ||
307 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
308 | struct GNUNET_PeerIdentity *pids; | ||
309 | struct GNUNET_MQ_Envelope *env; | ||
310 | unsigned int path_length; | ||
311 | |||
312 | cc->task = NULL; | ||
313 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
314 | path_length = GCPP_get_length (cc->path); | ||
315 | env = GNUNET_MQ_msg_extra (create_msg, | ||
316 | path_length * sizeof (struct GNUNET_PeerIdentity), | ||
317 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
318 | create_msg->cid = cc->cid; | ||
319 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
320 | for (unsigned int i=0;i<path_length;i++) | ||
321 | pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | ||
322 | i)); | ||
323 | cc->env = env; | ||
324 | cc->mqm_ready = GNUNET_NO; | ||
325 | cc->state = CADET_CONNECTION_READY; | ||
326 | GCP_send (cc->mq_man, | ||
327 | env); | ||
328 | } | ||
329 | |||
330 | |||
331 | /** | ||
332 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
333 | * connection that we already have. Either our ACK got lost | ||
334 | * or something is fishy. Consider retransmitting the ACK. | ||
335 | * | ||
336 | * @param cc connection that got the duplicate CREATE | ||
337 | */ | ||
338 | void | ||
339 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
340 | { | ||
341 | if (GNUNET_YES == cc->mqm_ready) | ||
342 | { | ||
343 | /* Tell tunnel that we are not ready for transmission anymore | ||
344 | (until CREATE_ACK is done) */ | ||
345 | cc->ready_cb (cc->ready_cb_cls, | ||
346 | GNUNET_NO); | ||
347 | |||
348 | /* Revert back to the state of having only received the 'CREATE', | ||
349 | and immediately proceed to send the CREATE_ACK. */ | ||
350 | cc->state = CADET_CONNECTION_CREATE_RECEIVED; | ||
351 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
352 | cc); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | /* We are currently sending something else back, which | ||
357 | can only be an ACK or payload, either of which would | ||
358 | do. So actually no need to do anything. */ | ||
359 | } | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * There has been a change in the message queue existence for our | ||
365 | * peer at the first hop. Adjust accordingly. | ||
366 | * | ||
367 | * @param cls the `struct CadetConnection` | ||
368 | * @param available #GNUNET_YES if sending is now possible, | ||
369 | * #GNUNET_NO if sending is no longer possible | ||
370 | * #GNUNET_SYSERR if sending is no longer possible | ||
371 | * and the last envelope was discarded | ||
372 | */ | ||
373 | static void | ||
374 | manage_first_hop_mq (void *cls, | ||
375 | int available) | ||
376 | { | ||
377 | struct CadetConnection *cc = cls; | ||
378 | |||
379 | if (GNUNET_YES != available) | ||
380 | { | ||
381 | /* Connection is down, for now... */ | ||
382 | cc->mqm_ready = GNUNET_NO; | ||
383 | cc->state = CADET_CONNECTION_NEW; | ||
384 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
385 | if (NULL != cc->task) | ||
386 | { | ||
387 | GNUNET_SCHEDULER_cancel (cc->task); | ||
388 | cc->task = NULL; | ||
389 | } | ||
390 | cc->ready_cb (cc->ready_cb_cls, | ||
391 | GNUNET_NO); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | cc->mqm_ready = GNUNET_YES; | ||
396 | switch (cc->state) | ||
397 | { | ||
398 | case CADET_CONNECTION_NEW: | ||
399 | /* Transmit immediately */ | ||
400 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | ||
401 | cc); | ||
402 | break; | ||
403 | case CADET_CONNECTION_SENDING_CREATE: | ||
404 | /* Should not be possible to be called in this state. */ | ||
405 | GNUNET_assert (0); | ||
406 | break; | ||
407 | case CADET_CONNECTION_SENT: | ||
408 | /* Retry a bit later... */ | ||
409 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
410 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
411 | &send_create, | ||
412 | cc); | ||
413 | break; | ||
414 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
415 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
416 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
417 | cc); | ||
418 | break; | ||
419 | case CADET_CONNECTION_READY: | ||
420 | cc->ready_cb (cc->ready_cb_cls, | ||
421 | GNUNET_YES); | ||
422 | break; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | |||
427 | /** | ||
428 | * Create a connection to @a destination via @a path and notify @a cb | ||
429 | * whenever we are ready for more data. Shared logic independent of | ||
430 | * who is initiating the connection. | ||
431 | * | ||
432 | * @param destination where to go | ||
433 | * @param path which path to take (may not be the full path) | ||
434 | * @param ct which tunnel uses this connection | ||
435 | * @param init_state initial state for the connection | ||
436 | * @param ready_cb function to call when ready to transmit | ||
437 | * @param ready_cb_cls closure for @a cb | ||
438 | * @return handle to the connection | ||
439 | */ | ||
440 | static struct CadetConnection * | ||
441 | connection_create (struct CadetPeer *destination, | ||
442 | struct CadetPeerPath *path, | ||
443 | struct CadetTConnection *ct, | ||
444 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
445 | enum CadetConnectionState init_state, | ||
446 | GCC_ReadyCallback ready_cb, | ||
447 | void *ready_cb_cls) | ||
448 | { | ||
449 | struct CadetConnection *cc; | ||
450 | struct CadetPeer *first_hop; | ||
451 | unsigned int off; | ||
452 | |||
453 | off = GCPP_find_peer (path, | ||
454 | destination); | ||
455 | GNUNET_assert (UINT_MAX > off); | ||
456 | cc = GNUNET_new (struct CadetConnection); | ||
457 | cc->state = init_state; | ||
458 | cc->ct = ct; | ||
459 | cc->cid = *cid; | ||
460 | GNUNET_assert (GNUNET_OK == | ||
461 | GNUNET_CONTAINER_multishortmap_put (connections, | ||
462 | &GCC_get_id (cc)->connection_of_tunnel, | ||
463 | cc, | ||
464 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
465 | cc->ready_cb = ready_cb; | ||
466 | cc->ready_cb_cls = ready_cb_cls; | ||
467 | cc->path = path; | ||
468 | cc->off = off; | ||
469 | GCPP_add_connection (path, | ||
470 | off, | ||
471 | cc); | ||
472 | for (unsigned int i=0;i<off;i++) | ||
473 | GCP_add_connection (GCPP_get_peer_at_offset (path, | ||
474 | off), | ||
475 | cc); | ||
476 | |||
477 | first_hop = GCPP_get_peer_at_offset (path, | ||
478 | 0); | ||
479 | cc->mq_man = GCP_request_mq (first_hop, | ||
480 | &manage_first_hop_mq, | ||
481 | cc); | ||
482 | return cc; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Create a connection to @a destination via @a path and | ||
488 | * notify @a cb whenever we are ready for more data. This | ||
489 | * is an inbound tunnel, so we must use the existing @a cid | ||
490 | * | ||
491 | * @param destination where to go | ||
492 | * @param path which path to take (may not be the full path) | ||
493 | * @param ct which tunnel uses this connection | ||
494 | * @param ready_cb function to call when ready to transmit | ||
495 | * @param ready_cb_cls closure for @a cb | ||
496 | * @return handle to the connection | ||
497 | */ | ||
498 | struct CadetConnection * | ||
499 | GCC_create_inbound (struct CadetPeer *destination, | ||
500 | struct CadetPeerPath *path, | ||
501 | struct CadetTConnection *ct, | ||
502 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
503 | GCC_ReadyCallback ready_cb, | ||
504 | void *ready_cb_cls) | ||
505 | { | ||
506 | return connection_create (destination, | ||
507 | path, | ||
508 | ct, | ||
509 | cid, | ||
510 | CADET_CONNECTION_CREATE_RECEIVED, | ||
511 | ready_cb, | ||
512 | ready_cb_cls); | ||
513 | } | ||
514 | |||
515 | |||
516 | /** | ||
517 | * Create a connection to @a destination via @a path and | ||
518 | * notify @a cb whenever we are ready for more data. | ||
519 | * | ||
520 | * @param destination where to go | ||
521 | * @param path which path to take (may not be the full path) | ||
522 | * @param ct tunnel that uses the connection | ||
523 | * @param ready_cb function to call when ready to transmit | ||
524 | * @param ready_cb_cls closure for @a cb | ||
525 | * @return handle to the connection | ||
526 | */ | ||
527 | struct CadetConnection * | ||
528 | GCC_create (struct CadetPeer *destination, | ||
529 | struct CadetPeerPath *path, | ||
530 | struct CadetTConnection *ct, | ||
531 | GCC_ReadyCallback ready_cb, | ||
532 | void *ready_cb_cls) | ||
533 | { | ||
534 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
535 | |||
536 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
537 | &cid, | ||
538 | sizeof (cid)); | ||
539 | return connection_create (destination, | ||
540 | path, | ||
541 | ct, | ||
542 | &cid, | ||
543 | CADET_CONNECTION_NEW, | ||
544 | ready_cb, | ||
545 | ready_cb_cls); | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Transmit message @a msg via connection @a cc. Must only be called | ||
551 | * (once) after the connection has signalled that it is ready via the | ||
552 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
553 | * connection is right now ready for transmission. | ||
554 | * | ||
555 | * @param cc connection identification | ||
556 | * @param env envelope with message to transmit; must NOT | ||
557 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
558 | */ | ||
559 | void | ||
560 | GCC_transmit (struct CadetConnection *cc, | ||
561 | struct GNUNET_MQ_Envelope *env) | ||
562 | { | ||
563 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
564 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); | ||
565 | cc->mqm_ready = GNUNET_NO; | ||
566 | GCP_send (cc->mq_man, | ||
567 | env); | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Obtain the path used by this connection. | ||
573 | * | ||
574 | * @param cc connection | ||
575 | * @return path to @a cc | ||
576 | */ | ||
577 | struct CadetPeerPath * | ||
578 | GCC_get_path (struct CadetConnection *cc) | ||
579 | { | ||
580 | return cc->path; | ||
581 | } | ||
582 | |||
583 | |||
584 | /** | ||
585 | * Obtain unique ID for the connection. | ||
586 | * | ||
587 | * @param cc connection. | ||
588 | * @return unique number of the connection | ||
589 | */ | ||
590 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
591 | GCC_get_id (struct CadetConnection *cc) | ||
592 | { | ||
593 | return &cc->cid; | ||
594 | } | ||
595 | |||
596 | |||
597 | /** | ||
598 | * Get a (static) string for a connection. | ||
599 | * | ||
600 | * @param cc Connection. | ||
601 | */ | ||
602 | const char * | ||
603 | GCC_2s (const struct CadetConnection *cc) | ||
604 | { | ||
605 | static char buf[128]; | ||
606 | |||
607 | if (NULL == cc) | ||
608 | return "Connection(NULL)"; | ||
609 | |||
610 | if (NULL != cc->ct) | ||
611 | { | ||
612 | GNUNET_snprintf (buf, | ||
613 | sizeof (buf), | ||
614 | "Connection(%s(Tunnel(%s)))", | ||
615 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
616 | GCT_2s (cc->ct->t)); | ||
617 | return buf; | ||
618 | } | ||
619 | GNUNET_snprintf (buf, | ||
620 | sizeof (buf), | ||
621 | "Connection(%s(Tunnel(NULL)))", | ||
622 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
623 | return buf; | ||
624 | } | ||
625 | |||
626 | |||
627 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Log connection info. | ||
632 | * | ||
633 | * @param cc connection | ||
634 | * @param level Debug level to use. | ||
635 | */ | ||
636 | void | ||
637 | GCC_debug (struct CadetConnection *cc, | ||
638 | enum GNUNET_ErrorType level) | ||
639 | { | ||
640 | int do_log; | ||
641 | char *s; | ||
642 | |||
643 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
644 | "cadet-con", | ||
645 | __FILE__, __FUNCTION__, __LINE__); | ||
646 | if (0 == do_log) | ||
647 | return; | ||
648 | if (NULL == cc) | ||
649 | { | ||
650 | LOG2 (level, | ||
651 | "Connection (NULL)\n"); | ||
652 | return; | ||
653 | } | ||
654 | s = GCPP_2s (cc->path); | ||
655 | LOG2 (level, | ||
656 | "Connection %s to %s via path %s in state %d is %s\n", | ||
657 | GCC_2s (cc), | ||
658 | GCP_2s (cc->destination), | ||
659 | s, | ||
660 | cc->state, | ||
661 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
662 | GNUNET_free (s); | ||
663 | } | ||
664 | |||
665 | /* end of gnunet-service-cadet-new_connection.c */ | ||