diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_connection.c | 3176 |
1 files changed, 3176 insertions, 0 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c new file mode 100644 index 000000000..9c07e006b --- /dev/null +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -0,0 +1,3176 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001-2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.c | ||
23 | * @brief GNUnet CADET service connection handling | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | |||
30 | #include "gnunet_statistics_service.h" | ||
31 | |||
32 | #include "cadet_path.h" | ||
33 | #include "cadet_protocol.h" | ||
34 | #include "cadet.h" | ||
35 | #include "gnunet-service-cadet_connection.h" | ||
36 | #include "gnunet-service-cadet_peer.h" | ||
37 | #include "gnunet-service-cadet_tunnel.h" | ||
38 | |||
39 | |||
40 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__) | ||
41 | |||
42 | #define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ | ||
43 | GNUNET_TIME_UNIT_MINUTES,\ | ||
44 | 10) | ||
45 | #define AVG_MSGS 32 | ||
46 | |||
47 | |||
48 | /******************************************************************************/ | ||
49 | /******************************** STRUCTS **********************************/ | ||
50 | /******************************************************************************/ | ||
51 | |||
52 | /** | ||
53 | * Struct to encapsulate all the Flow Control information to a peer to which | ||
54 | * we are directly connected (on a core level). | ||
55 | */ | ||
56 | struct CadetFlowControl | ||
57 | { | ||
58 | /** | ||
59 | * Connection this controls. | ||
60 | */ | ||
61 | struct CadetConnection *c; | ||
62 | |||
63 | /** | ||
64 | * How many messages are in the queue on this connection. | ||
65 | */ | ||
66 | unsigned int queue_n; | ||
67 | |||
68 | /** | ||
69 | * How many messages do we accept in the queue. | ||
70 | */ | ||
71 | unsigned int queue_max; | ||
72 | |||
73 | /** | ||
74 | * ID of the last packet sent towards the peer. | ||
75 | */ | ||
76 | uint32_t last_pid_sent; | ||
77 | |||
78 | /** | ||
79 | * ID of the last packet received from the peer. | ||
80 | */ | ||
81 | uint32_t last_pid_recv; | ||
82 | |||
83 | /** | ||
84 | * Last ACK sent to the peer (peer can't send more than this PID). | ||
85 | */ | ||
86 | uint32_t last_ack_sent; | ||
87 | |||
88 | /** | ||
89 | * Last ACK sent towards the origin (for traffic towards leaf node). | ||
90 | */ | ||
91 | uint32_t last_ack_recv; | ||
92 | |||
93 | /** | ||
94 | * Task to poll the peer in case of a lost ACK causes stall. | ||
95 | */ | ||
96 | GNUNET_SCHEDULER_TaskIdentifier poll_task; | ||
97 | |||
98 | /** | ||
99 | * How frequently to poll for ACKs. | ||
100 | */ | ||
101 | struct GNUNET_TIME_Relative poll_time; | ||
102 | |||
103 | /** | ||
104 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
105 | */ | ||
106 | struct CadetConnectionQueue *poll_msg; | ||
107 | |||
108 | /** | ||
109 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
110 | */ | ||
111 | struct CadetConnectionQueue *ack_msg; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Keep a record of the last messages sent on this connection. | ||
116 | */ | ||
117 | struct CadetConnectionPerformance | ||
118 | { | ||
119 | /** | ||
120 | * Circular buffer for storing measurements. | ||
121 | */ | ||
122 | double usecsperbyte[AVG_MSGS]; | ||
123 | |||
124 | /** | ||
125 | * Running average of @c usecsperbyte. | ||
126 | */ | ||
127 | double avg; | ||
128 | |||
129 | /** | ||
130 | * How many values of @c usecsperbyte are valid. | ||
131 | */ | ||
132 | uint16_t size; | ||
133 | |||
134 | /** | ||
135 | * Index of the next "free" position in @c usecsperbyte. | ||
136 | */ | ||
137 | uint16_t idx; | ||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Struct containing all information regarding a connection to a peer. | ||
143 | */ | ||
144 | struct CadetConnection | ||
145 | { | ||
146 | /** | ||
147 | * Tunnel this connection is part of. | ||
148 | */ | ||
149 | struct CadetTunnel3 *t; | ||
150 | |||
151 | /** | ||
152 | * Flow control information for traffic fwd. | ||
153 | */ | ||
154 | struct CadetFlowControl fwd_fc; | ||
155 | |||
156 | /** | ||
157 | * Flow control information for traffic bck. | ||
158 | */ | ||
159 | struct CadetFlowControl bck_fc; | ||
160 | |||
161 | /** | ||
162 | * Measure connection performance on the endpoint. | ||
163 | */ | ||
164 | struct CadetConnectionPerformance *perf; | ||
165 | |||
166 | /** | ||
167 | * ID of the connection. | ||
168 | */ | ||
169 | struct GNUNET_CADET_Hash id; | ||
170 | |||
171 | /** | ||
172 | * State of the connection. | ||
173 | */ | ||
174 | enum CadetConnectionState state; | ||
175 | |||
176 | /** | ||
177 | * Path being used for the tunnel. At the origin of the connection | ||
178 | * it's a pointer to the destination's path pool, otherwise just a copy. | ||
179 | */ | ||
180 | struct CadetPeerPath *path; | ||
181 | |||
182 | /** | ||
183 | * Position of the local peer in the path. | ||
184 | */ | ||
185 | unsigned int own_pos; | ||
186 | |||
187 | /** | ||
188 | * Task to keep the used paths alive at the owner, | ||
189 | * time tunnel out on all the other peers. | ||
190 | */ | ||
191 | GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task; | ||
192 | |||
193 | /** | ||
194 | * Task to keep the used paths alive at the destination, | ||
195 | * time tunnel out on all the other peers. | ||
196 | */ | ||
197 | GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task; | ||
198 | |||
199 | /** | ||
200 | * Queue handle for maintainance traffic. One handle for FWD and BCK since | ||
201 | * one peer never needs to maintain both directions (no loopback connections). | ||
202 | */ | ||
203 | struct CadetPeerQueue *maintenance_q; | ||
204 | |||
205 | /** | ||
206 | * Counter to do exponential backoff when creating a connection (max 64). | ||
207 | */ | ||
208 | unsigned short create_retry; | ||
209 | |||
210 | /** | ||
211 | * Pending message count. | ||
212 | */ | ||
213 | int pending_messages; | ||
214 | |||
215 | /** | ||
216 | * Destroy flag: if true, destroy on last message. | ||
217 | */ | ||
218 | int destroy; | ||
219 | }; | ||
220 | |||
221 | /** | ||
222 | * Handle for messages queued but not yet sent. | ||
223 | */ | ||
224 | struct CadetConnectionQueue | ||
225 | { | ||
226 | /** | ||
227 | * Peer queue handle, to cancel if necessary. | ||
228 | */ | ||
229 | struct CadetPeerQueue *q; | ||
230 | |||
231 | /** | ||
232 | * Was this a forced message? (Do not account for it) | ||
233 | */ | ||
234 | int forced; | ||
235 | |||
236 | /** | ||
237 | * Continuation to call once sent. | ||
238 | */ | ||
239 | GMC_sent cont; | ||
240 | |||
241 | /** | ||
242 | * Closure for @c cont. | ||
243 | */ | ||
244 | void *cont_cls; | ||
245 | }; | ||
246 | |||
247 | /******************************************************************************/ | ||
248 | /******************************* GLOBALS ***********************************/ | ||
249 | /******************************************************************************/ | ||
250 | |||
251 | /** | ||
252 | * Global handle to the statistics service. | ||
253 | */ | ||
254 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
255 | |||
256 | /** | ||
257 | * Local peer own ID (memory efficient handle). | ||
258 | */ | ||
259 | extern GNUNET_PEER_Id myid; | ||
260 | |||
261 | /** | ||
262 | * Local peer own ID (full value). | ||
263 | */ | ||
264 | extern struct GNUNET_PeerIdentity my_full_id; | ||
265 | |||
266 | /** | ||
267 | * Connections known, indexed by cid (CadetConnection). | ||
268 | */ | ||
269 | static struct GNUNET_CONTAINER_MultiHashMap *connections; | ||
270 | |||
271 | /** | ||
272 | * How many connections are we willing to maintain. | ||
273 | * Local connections are always allowed, even if there are more connections than max. | ||
274 | */ | ||
275 | static unsigned long long max_connections; | ||
276 | |||
277 | /** | ||
278 | * How many messages *in total* are we willing to queue, divide by number of | ||
279 | * connections to get connection queue size. | ||
280 | */ | ||
281 | static unsigned long long max_msgs_queue; | ||
282 | |||
283 | /** | ||
284 | * How often to send path keepalives. Paths timeout after 4 missed. | ||
285 | */ | ||
286 | static struct GNUNET_TIME_Relative refresh_connection_time; | ||
287 | |||
288 | /** | ||
289 | * How often to send path create / ACKs. | ||
290 | */ | ||
291 | static struct GNUNET_TIME_Relative create_connection_time; | ||
292 | |||
293 | |||
294 | /******************************************************************************/ | ||
295 | /******************************** STATIC ***********************************/ | ||
296 | /******************************************************************************/ | ||
297 | |||
298 | #if 0 // avoid compiler warning for unused static function | ||
299 | static void | ||
300 | fc_debug (struct CadetFlowControl *fc) | ||
301 | { | ||
302 | LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", | ||
303 | fc->last_pid_recv, fc->last_ack_sent); | ||
304 | LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", | ||
305 | fc->last_pid_sent, fc->last_ack_recv); | ||
306 | LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", | ||
307 | fc->queue_n, fc->queue_max); | ||
308 | } | ||
309 | |||
310 | static void | ||
311 | connection_debug (struct CadetConnection *c) | ||
312 | { | ||
313 | if (NULL == c) | ||
314 | { | ||
315 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n"); | ||
316 | return; | ||
317 | } | ||
318 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", | ||
319 | peer2s (c->t->peer), GMC_2s (c)); | ||
320 | LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", | ||
321 | c->state, c->pending_messages); | ||
322 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
323 | fc_debug (&c->fwd_fc); | ||
324 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
325 | fc_debug (&c->bck_fc); | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Schedule next keepalive task, taking in consideration | ||
332 | * the connection state and number of retries. | ||
333 | * | ||
334 | * @param c Connection for which to schedule the next keepalive. | ||
335 | * @param fwd Direction for the next keepalive. | ||
336 | */ | ||
337 | static void | ||
338 | schedule_next_keepalive (struct CadetConnection *c, int fwd); | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Resets the connection timeout task, some other message has done the | ||
343 | * task's job. | ||
344 | * - For the first peer on the direction this means to send | ||
345 | * a keepalive or a path confirmation message (either create or ACK). | ||
346 | * - For all other peers, this means to destroy the connection, | ||
347 | * due to lack of activity. | ||
348 | * Starts the timeout if no timeout was running (connection just created). | ||
349 | * | ||
350 | * @param c Connection whose timeout to reset. | ||
351 | * @param fwd Is this forward? | ||
352 | */ | ||
353 | static void | ||
354 | connection_reset_timeout (struct CadetConnection *c, int fwd); | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Get string description for tunnel state. Reentrant. | ||
359 | * | ||
360 | * @param s Tunnel state. | ||
361 | * | ||
362 | * @return String representation. | ||
363 | */ | ||
364 | static const char * | ||
365 | GMC_state2s (enum CadetConnectionState s) | ||
366 | { | ||
367 | switch (s) | ||
368 | { | ||
369 | case CADET_CONNECTION_NEW: | ||
370 | return "CADET_CONNECTION_NEW"; | ||
371 | case CADET_CONNECTION_SENT: | ||
372 | return "CADET_CONNECTION_SENT"; | ||
373 | case CADET_CONNECTION_ACK: | ||
374 | return "CADET_CONNECTION_ACK"; | ||
375 | case CADET_CONNECTION_READY: | ||
376 | return "CADET_CONNECTION_READY"; | ||
377 | case CADET_CONNECTION_DESTROYED: | ||
378 | return "CADET_CONNECTION_DESTROYED"; | ||
379 | default: | ||
380 | return "CADET_CONNECTION_STATE_ERROR"; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * Initialize a Flow Control structure to the initial state. | ||
387 | * | ||
388 | * @param fc Flow Control structure to initialize. | ||
389 | */ | ||
390 | static void | ||
391 | fc_init (struct CadetFlowControl *fc) | ||
392 | { | ||
393 | fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */ | ||
394 | fc->last_pid_recv = (uint32_t) -1; | ||
395 | fc->last_ack_sent = (uint32_t) 0; | ||
396 | fc->last_ack_recv = (uint32_t) 0; | ||
397 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
398 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
399 | fc->queue_n = 0; | ||
400 | fc->queue_max = (max_msgs_queue / max_connections) + 1; | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Find a connection. | ||
406 | * | ||
407 | * @param cid Connection ID. | ||
408 | */ | ||
409 | static struct CadetConnection * | ||
410 | connection_get (const struct GNUNET_CADET_Hash *cid) | ||
411 | { | ||
412 | return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid)); | ||
413 | } | ||
414 | |||
415 | |||
416 | static void | ||
417 | connection_change_state (struct CadetConnection* c, | ||
418 | enum CadetConnectionState state) | ||
419 | { | ||
420 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
421 | "Connection %s state %s -> %s\n", | ||
422 | GMC_2s (c), GMC_state2s (c->state), GMC_state2s (state)); | ||
423 | if (CADET_CONNECTION_DESTROYED == c->state) | ||
424 | { | ||
425 | LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n"); | ||
426 | return; | ||
427 | } | ||
428 | c->state = state; | ||
429 | if (CADET_CONNECTION_READY == state) | ||
430 | c->create_retry = 1; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Callback called when a queued ACK message is sent. | ||
436 | * | ||
437 | * @param cls Closure (FC). | ||
438 | * @param c Connection this message was on. | ||
439 | * @param q Queue handler this call invalidates. | ||
440 | * @param type Type of message sent. | ||
441 | * @param fwd Was this a FWD going message? | ||
442 | * @param size Size of the message. | ||
443 | */ | ||
444 | static void | ||
445 | ack_sent (void *cls, | ||
446 | struct CadetConnection *c, | ||
447 | struct CadetConnectionQueue *q, | ||
448 | uint16_t type, int fwd, size_t size) | ||
449 | { | ||
450 | struct CadetFlowControl *fc = cls; | ||
451 | |||
452 | fc->ack_msg = NULL; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Send an ACK on the connection, informing the predecessor about | ||
458 | * the available buffer space. Should not be called in case the peer | ||
459 | * is origin (no predecessor) in the @c fwd direction. | ||
460 | * | ||
461 | * Note that for fwd ack, the FWD mean forward *traffic* (root->dest), | ||
462 | * the ACK itself goes "back" (dest->root). | ||
463 | * | ||
464 | * @param c Connection on which to send the ACK. | ||
465 | * @param buffer How much space free to advertise? | ||
466 | * @param fwd Is this FWD ACK? (Going dest -> root) | ||
467 | * @param force Don't optimize out. | ||
468 | */ | ||
469 | static void | ||
470 | send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force) | ||
471 | { | ||
472 | struct CadetFlowControl *next_fc; | ||
473 | struct CadetFlowControl *prev_fc; | ||
474 | struct GNUNET_CADET_ACK msg; | ||
475 | uint32_t ack; | ||
476 | int delta; | ||
477 | |||
478 | /* If origin, there is no connection to send ACKs. Wrong function! */ | ||
479 | if (GMC_is_origin (c, fwd)) | ||
480 | { | ||
481 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection %s is origin in %s\n", | ||
482 | GMC_2s (c), GM_f2s (fwd)); | ||
483 | GNUNET_break (0); | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | next_fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
488 | prev_fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
489 | |||
490 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection send %s ack on %s\n", | ||
491 | GM_f2s (fwd), GMC_2s (c)); | ||
492 | |||
493 | /* Check if we need to transmit the ACK. */ | ||
494 | delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv; | ||
495 | if (3 < delta && buffer < delta && GNUNET_NO == force) | ||
496 | { | ||
497 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n"); | ||
498 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
499 | " last pid recv: %u, last ack sent: %u\n", | ||
500 | prev_fc->last_pid_recv, prev_fc->last_ack_sent); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Ok, ACK might be necessary, what PID to ACK? */ | ||
505 | ack = prev_fc->last_pid_recv + buffer; | ||
506 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); | ||
507 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
508 | " last pid %u, last ack %u, qmax %u, q %u\n", | ||
509 | prev_fc->last_pid_recv, prev_fc->last_ack_sent, | ||
510 | next_fc->queue_max, next_fc->queue_n); | ||
511 | if (ack == prev_fc->last_ack_sent && GNUNET_NO == force) | ||
512 | { | ||
513 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | /* Check if message is already in queue */ | ||
518 | if (NULL != prev_fc->ack_msg) | ||
519 | { | ||
520 | if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent)) | ||
521 | { | ||
522 | LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); | ||
523 | GMC_cancel (prev_fc->ack_msg); | ||
524 | /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */ | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n"); | ||
529 | return; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | prev_fc->last_ack_sent = ack; | ||
534 | |||
535 | /* Build ACK message and send on connection */ | ||
536 | msg.header.size = htons (sizeof (msg)); | ||
537 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK); | ||
538 | msg.ack = htonl (ack); | ||
539 | msg.cid = c->id; | ||
540 | |||
541 | prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, | ||
542 | GNUNET_MESSAGE_TYPE_CADET_ACK, | ||
543 | ack, c, !fwd, GNUNET_YES, | ||
544 | &ack_sent, prev_fc); | ||
545 | } | ||
546 | |||
547 | |||
548 | /** | ||
549 | * Callback called when a connection queued message is sent. | ||
550 | * | ||
551 | * Calculates the average time and connection packet tracking. | ||
552 | * | ||
553 | * @param cls Closure (ConnectionQueue Handle). | ||
554 | * @param c Connection this message was on. | ||
555 | * @param sent Was it really sent? (Could have been canceled) | ||
556 | * @param type Type of message sent. | ||
557 | * @param pid Packet ID, or 0 if not applicable (create, destroy, etc). | ||
558 | * @param fwd Was this a FWD going message? | ||
559 | * @param size Size of the message. | ||
560 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
561 | */ | ||
562 | static void | ||
563 | conn_message_sent (void *cls, | ||
564 | struct CadetConnection *c, int sent, | ||
565 | uint16_t type, uint32_t pid, int fwd, size_t size, | ||
566 | struct GNUNET_TIME_Relative wait) | ||
567 | { | ||
568 | struct CadetConnectionPerformance *p; | ||
569 | struct CadetFlowControl *fc; | ||
570 | struct CadetConnectionQueue *q = cls; | ||
571 | double usecsperbyte; | ||
572 | int forced; | ||
573 | |||
574 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection message_sent\n"); | ||
575 | |||
576 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
577 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s\n", | ||
578 | sent ? "" : "not ", GM_f2s (fwd), GM_m2s (type)); | ||
579 | if (NULL != q) | ||
580 | { | ||
581 | forced = q->forced; | ||
582 | if (NULL != q->cont) | ||
583 | { | ||
584 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n"); | ||
585 | q->cont (q->cont_cls, c, q, type, fwd, size); | ||
586 | } | ||
587 | GNUNET_free (q); | ||
588 | } | ||
589 | else if (type == GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED) | ||
590 | { | ||
591 | /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */ | ||
592 | forced = GNUNET_YES; | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | forced = GNUNET_NO; | ||
597 | } | ||
598 | if (NULL == c) | ||
599 | { | ||
600 | GNUNET_break (type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN || | ||
601 | type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
602 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", | ||
603 | GM_m2s (type)); | ||
604 | return; | ||
605 | } | ||
606 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); | ||
607 | c->pending_messages--; | ||
608 | if (GNUNET_YES == c->destroy && 0 == c->pending_messages) | ||
609 | { | ||
610 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); | ||
611 | GMC_destroy (c); | ||
612 | return; | ||
613 | } | ||
614 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ | ||
615 | switch (type) | ||
616 | { | ||
617 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
618 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
619 | c->maintenance_q = NULL; | ||
620 | /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ | ||
621 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) | ||
622 | schedule_next_keepalive (c, fwd); | ||
623 | break; | ||
624 | |||
625 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
626 | if (GNUNET_YES == sent) | ||
627 | { | ||
628 | GNUNET_assert (NULL != q); | ||
629 | fc->last_pid_sent = pid; // FIXME | ||
630 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
631 | connection_reset_timeout (c, fwd); | ||
632 | } | ||
633 | |||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); | ||
635 | if (GNUNET_NO == forced) | ||
636 | { | ||
637 | fc->queue_n--; | ||
638 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
639 | "! accounting pid %u\n", | ||
640 | fc->last_pid_sent); | ||
641 | } | ||
642 | else | ||
643 | { | ||
644 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
645 | "! forced, Q_N not accounting pid %u\n", | ||
646 | fc->last_pid_sent); | ||
647 | } | ||
648 | break; | ||
649 | |||
650 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
651 | if (GNUNET_YES == sent) | ||
652 | connection_reset_timeout (c, fwd); | ||
653 | break; | ||
654 | |||
655 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
656 | fc->poll_msg = NULL; | ||
657 | break; | ||
658 | |||
659 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
660 | fc->ack_msg = NULL; | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | break; | ||
665 | } | ||
666 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); | ||
667 | |||
668 | if (NULL == c->perf) | ||
669 | return; /* Only endpoints are interested in timing. */ | ||
670 | |||
671 | p = c->perf; | ||
672 | usecsperbyte = ((double) wait.rel_value_us) / size; | ||
673 | if (p->size == AVG_MSGS) | ||
674 | { | ||
675 | /* Array is full. Substract oldest value, add new one and store. */ | ||
676 | p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
677 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
678 | p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
679 | } | ||
680 | else | ||
681 | { | ||
682 | /* Array not yet full. Add current value to avg and store. */ | ||
683 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
684 | p->avg *= p->size; | ||
685 | p->avg += p->usecsperbyte[p->idx]; | ||
686 | p->size++; | ||
687 | p->avg /= p->size; | ||
688 | } | ||
689 | p->idx = (p->idx + 1) % AVG_MSGS; | ||
690 | } | ||
691 | |||
692 | |||
693 | /** | ||
694 | * Get the previous hop in a connection | ||
695 | * | ||
696 | * @param c Connection. | ||
697 | * | ||
698 | * @return Previous peer in the connection. | ||
699 | */ | ||
700 | static struct CadetPeer * | ||
701 | get_prev_hop (const struct CadetConnection *c) | ||
702 | { | ||
703 | GNUNET_PEER_Id id; | ||
704 | |||
705 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get prev hop %s [%u/%u]\n", | ||
706 | GMC_2s (c), c->own_pos, c->path->length); | ||
707 | if (0 == c->own_pos || c->path->length < 2) | ||
708 | id = c->path->peers[0]; | ||
709 | else | ||
710 | id = c->path->peers[c->own_pos - 1]; | ||
711 | |||
712 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
713 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
714 | |||
715 | return GMP_get_short (id); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * Get the next hop in a connection | ||
721 | * | ||
722 | * @param c Connection. | ||
723 | * | ||
724 | * @return Next peer in the connection. | ||
725 | */ | ||
726 | static struct CadetPeer * | ||
727 | get_next_hop (const struct CadetConnection *c) | ||
728 | { | ||
729 | GNUNET_PEER_Id id; | ||
730 | |||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n", | ||
732 | GMC_2s (c), c->own_pos, c->path->length); | ||
733 | if ((c->path->length - 1) == c->own_pos || c->path->length < 2) | ||
734 | id = c->path->peers[c->path->length - 1]; | ||
735 | else | ||
736 | id = c->path->peers[c->own_pos + 1]; | ||
737 | |||
738 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
739 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
740 | |||
741 | return GMP_get_short (id); | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Get the hop in a connection. | ||
747 | * | ||
748 | * @param c Connection. | ||
749 | * @param fwd Next hop? | ||
750 | * | ||
751 | * @return Next peer in the connection. | ||
752 | */ | ||
753 | static struct CadetPeer * | ||
754 | get_hop (struct CadetConnection *c, int fwd) | ||
755 | { | ||
756 | if (fwd) | ||
757 | return get_next_hop (c); | ||
758 | return get_prev_hop (c); | ||
759 | } | ||
760 | |||
761 | |||
762 | /** | ||
763 | * Is traffic coming from this sender 'FWD' traffic? | ||
764 | * | ||
765 | * @param c Connection to check. | ||
766 | * @param sender Peer identity of neighbor. | ||
767 | * | ||
768 | * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore | ||
769 | * the traffic is 'FWD'. | ||
770 | * #GNUNET_NO for BCK. | ||
771 | * #GNUNET_SYSERR for errors. | ||
772 | */ | ||
773 | static int | ||
774 | is_fwd (const struct CadetConnection *c, | ||
775 | const struct GNUNET_PeerIdentity *sender) | ||
776 | { | ||
777 | GNUNET_PEER_Id id; | ||
778 | |||
779 | id = GNUNET_PEER_search (sender); | ||
780 | if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
781 | return GNUNET_YES; | ||
782 | |||
783 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
784 | return GNUNET_NO; | ||
785 | |||
786 | GNUNET_break (0); | ||
787 | return GNUNET_SYSERR; | ||
788 | } | ||
789 | |||
790 | |||
791 | /** | ||
792 | * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE | ||
793 | * or a first CONNECTION_ACK directed to us. | ||
794 | * | ||
795 | * @param connection Connection to confirm. | ||
796 | * @param fwd Should we send it FWD? (root->dest) | ||
797 | * (First (~SYNACK) goes BCK, second (~ACK) goes FWD) | ||
798 | */ | ||
799 | static void | ||
800 | send_connection_ack (struct CadetConnection *connection, int fwd) | ||
801 | { | ||
802 | struct CadetTunnel3 *t; | ||
803 | |||
804 | t = connection->t; | ||
805 | LOG (GNUNET_ERROR_TYPE_INFO, "===> {%14s ACK} on connection %s\n", | ||
806 | GM_f2s (!fwd), GMC_2s (connection)); | ||
807 | GMP_queue_add (get_hop (connection, fwd), NULL, | ||
808 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, | ||
809 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0, | ||
810 | sizeof (struct GNUNET_CADET_ConnectionACK), | ||
811 | connection, fwd, &conn_message_sent, NULL); | ||
812 | connection->pending_messages++; | ||
813 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (t)) | ||
814 | GMT_change_cstate (t, CADET_TUNNEL3_WAITING); | ||
815 | if (CADET_CONNECTION_READY != connection->state) | ||
816 | connection_change_state (connection, CADET_CONNECTION_SENT); | ||
817 | } | ||
818 | |||
819 | |||
820 | /** | ||
821 | * Send a notification that a connection is broken. | ||
822 | * | ||
823 | * @param c Connection that is broken. | ||
824 | * @param id1 Peer that has disconnected. | ||
825 | * @param id2 Peer that has disconnected. | ||
826 | * @param fwd Direction towards which to send it. | ||
827 | */ | ||
828 | static void | ||
829 | send_broken (struct CadetConnection *c, | ||
830 | const struct GNUNET_PeerIdentity *id1, | ||
831 | const struct GNUNET_PeerIdentity *id2, | ||
832 | int fwd) | ||
833 | { | ||
834 | struct GNUNET_CADET_ConnectionBroken msg; | ||
835 | |||
836 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); | ||
837 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
838 | msg.cid = c->id; | ||
839 | msg.peer1 = *id1; | ||
840 | msg.peer2 = *id2; | ||
841 | GMC_send_prebuilt_message (&msg.header, | ||
842 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0, | ||
843 | c, fwd, GNUNET_YES, NULL, NULL); | ||
844 | } | ||
845 | |||
846 | |||
847 | /** | ||
848 | * Send a notification that a connection is broken, when a connection | ||
849 | * isn't even known to the local peer. | ||
850 | * | ||
851 | * @param connection_id Connection ID. | ||
852 | * @param id1 Peer that has disconnected, probably local peer. | ||
853 | * @param id2 Peer that has disconnected can be NULL if unknown. | ||
854 | * @param peer Peer to notify (neighbor who sent the connection). | ||
855 | */ | ||
856 | static void | ||
857 | send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id, | ||
858 | const struct GNUNET_PeerIdentity *id1, | ||
859 | const struct GNUNET_PeerIdentity *id2, | ||
860 | const struct GNUNET_PeerIdentity *peer_id) | ||
861 | { | ||
862 | struct GNUNET_CADET_ConnectionBroken *msg; | ||
863 | struct CadetPeer *neighbor; | ||
864 | |||
865 | LOG (GNUNET_ERROR_TYPE_INFO, "===> BROKEN on unknown connection %s\n", | ||
866 | GNUNET_h2s (GM_h2hc (connection_id))); | ||
867 | |||
868 | msg = GNUNET_new (struct GNUNET_CADET_ConnectionBroken); | ||
869 | msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); | ||
870 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
871 | msg->cid = *connection_id; | ||
872 | msg->peer1 = *id1; | ||
873 | if (NULL != id2) | ||
874 | msg->peer2 = *id2; | ||
875 | else | ||
876 | memset (&msg->peer2, 0, sizeof (msg->peer2)); | ||
877 | neighbor = GMP_get (peer_id); | ||
878 | GMP_queue_add (neighbor, msg, | ||
879 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
880 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 2, | ||
881 | sizeof (struct GNUNET_CADET_ConnectionBroken), | ||
882 | NULL, GNUNET_SYSERR, /* connection, fwd */ | ||
883 | NULL, NULL); /* continuation */ | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Send keepalive packets for a connection. | ||
889 | * | ||
890 | * @param c Connection to keep alive.. | ||
891 | * @param fwd Is this a FWD keepalive? (owner -> dest). | ||
892 | */ | ||
893 | static void | ||
894 | send_connection_keepalive (struct CadetConnection *c, int fwd) | ||
895 | { | ||
896 | struct GNUNET_MessageHeader msg; | ||
897 | struct CadetFlowControl *fc; | ||
898 | |||
899 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
900 | "keepalive %s for connection %s\n", | ||
901 | GM_f2s (fwd), GMC_2s (c)); | ||
902 | |||
903 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
904 | if (0 < fc->queue_n) | ||
905 | { | ||
906 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); | ||
907 | } | ||
908 | |||
909 | GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO); | ||
910 | |||
911 | GNUNET_assert (NULL != c->t); | ||
912 | msg.size = htons (sizeof (msg)); | ||
913 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE); | ||
914 | |||
915 | GNUNET_assert (NULL == | ||
916 | GMT_send_prebuilt_message (&msg, c->t, c, | ||
917 | GNUNET_NO, NULL, NULL)); | ||
918 | } | ||
919 | |||
920 | |||
921 | /** | ||
922 | * Send CONNECTION_{CREATE/ACK} packets for a connection. | ||
923 | * | ||
924 | * @param c Connection for which to send the message. | ||
925 | * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK. | ||
926 | */ | ||
927 | static void | ||
928 | connection_recreate (struct CadetConnection *c, int fwd) | ||
929 | { | ||
930 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n"); | ||
931 | if (fwd) | ||
932 | GMC_send_create (c); | ||
933 | else | ||
934 | send_connection_ack (c, GNUNET_NO); | ||
935 | } | ||
936 | |||
937 | |||
938 | /** | ||
939 | * Generic connection timer management. | ||
940 | * Depending on the role of the peer in the connection will send the | ||
941 | * appropriate message (build or keepalive) | ||
942 | * | ||
943 | * @param c Conncetion to maintain. | ||
944 | * @param fwd Is FWD? | ||
945 | */ | ||
946 | static void | ||
947 | connection_maintain (struct CadetConnection *c, int fwd) | ||
948 | { | ||
949 | if (GNUNET_NO != c->destroy) | ||
950 | return; | ||
951 | |||
952 | if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (c->t)) | ||
953 | { | ||
954 | /* TODO DHT GET with RO_BART */ | ||
955 | return; | ||
956 | } | ||
957 | switch (c->state) | ||
958 | { | ||
959 | case CADET_CONNECTION_NEW: | ||
960 | GNUNET_break (0); | ||
961 | /* fall-through */ | ||
962 | case CADET_CONNECTION_SENT: | ||
963 | connection_recreate (c, fwd); | ||
964 | break; | ||
965 | case CADET_CONNECTION_READY: | ||
966 | send_connection_keepalive (c, fwd); | ||
967 | break; | ||
968 | default: | ||
969 | break; | ||
970 | } | ||
971 | } | ||
972 | |||
973 | |||
974 | |||
975 | /** | ||
976 | * Keep the connection alive. | ||
977 | * | ||
978 | * @param c Connection to keep alive. | ||
979 | * @param fwd Direction. | ||
980 | * @param shutdown Are we shutting down? (Don't send traffic) | ||
981 | * Non-zero value for true, not necessarily GNUNET_YES. | ||
982 | */ | ||
983 | static void | ||
984 | connection_keepalive (struct CadetConnection *c, int fwd, int shutdown) | ||
985 | { | ||
986 | LOG (GNUNET_ERROR_TYPE_DEBUG, "%s keepalive for %s\n", | ||
987 | GM_f2s (fwd), GMC_2s (c)); | ||
988 | |||
989 | if (fwd) | ||
990 | c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
991 | else | ||
992 | c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
993 | |||
994 | if (GNUNET_NO != shutdown) | ||
995 | return; | ||
996 | |||
997 | connection_maintain (c, fwd); | ||
998 | |||
999 | /* Next execution will be scheduled by message_sent */ | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /** | ||
1004 | * Keep the connection alive in the FWD direction. | ||
1005 | * | ||
1006 | * @param cls Closure (connection to keepalive). | ||
1007 | * @param tc TaskContext. | ||
1008 | */ | ||
1009 | static void | ||
1010 | connection_fwd_keepalive (void *cls, | ||
1011 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1012 | { | ||
1013 | connection_keepalive ((struct CadetConnection *) cls, | ||
1014 | GNUNET_YES, | ||
1015 | tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | /** | ||
1020 | * Keep the connection alive in the BCK direction. | ||
1021 | * | ||
1022 | * @param cls Closure (connection to keepalive). | ||
1023 | * @param tc TaskContext. | ||
1024 | */ | ||
1025 | static void | ||
1026 | connection_bck_keepalive (void *cls, | ||
1027 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1028 | { | ||
1029 | connection_keepalive ((struct CadetConnection *) cls, | ||
1030 | GNUNET_NO, | ||
1031 | tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /** | ||
1036 | * Schedule next keepalive task, taking in consideration | ||
1037 | * the connection state and number of retries. | ||
1038 | * | ||
1039 | * If the peer is not the origin, do nothing. | ||
1040 | * | ||
1041 | * @param c Connection for which to schedule the next keepalive. | ||
1042 | * @param fwd Direction for the next keepalive. | ||
1043 | */ | ||
1044 | static void | ||
1045 | schedule_next_keepalive (struct CadetConnection *c, int fwd) | ||
1046 | { | ||
1047 | struct GNUNET_TIME_Relative delay; | ||
1048 | GNUNET_SCHEDULER_TaskIdentifier *task_id; | ||
1049 | GNUNET_SCHEDULER_Task keepalive_task; | ||
1050 | |||
1051 | if (GNUNET_NO == GMC_is_origin (c, fwd)) | ||
1052 | return; | ||
1053 | |||
1054 | /* Calculate delay to use, depending on the state of the connection */ | ||
1055 | if (CADET_CONNECTION_READY == c->state) | ||
1056 | { | ||
1057 | delay = refresh_connection_time; | ||
1058 | } | ||
1059 | else | ||
1060 | { | ||
1061 | if (1 > c->create_retry) | ||
1062 | c->create_retry = 1; | ||
1063 | delay = GNUNET_TIME_relative_multiply (create_connection_time, | ||
1064 | c->create_retry); | ||
1065 | if (c->create_retry < 64) | ||
1066 | c->create_retry *= 2; | ||
1067 | } | ||
1068 | |||
1069 | /* Select direction-dependent parameters */ | ||
1070 | if (GNUNET_YES == fwd) | ||
1071 | { | ||
1072 | task_id = &c->fwd_maintenance_task; | ||
1073 | keepalive_task = &connection_fwd_keepalive; | ||
1074 | } | ||
1075 | else | ||
1076 | { | ||
1077 | task_id = &c->bck_maintenance_task; | ||
1078 | keepalive_task = &connection_bck_keepalive; | ||
1079 | } | ||
1080 | |||
1081 | /* Check that no one scheduled it before us */ | ||
1082 | if (GNUNET_SCHEDULER_NO_TASK != *task_id) | ||
1083 | { | ||
1084 | /* No need for a _break. It can happen for instance when sending a SYNACK | ||
1085 | * for a duplicate SYN: the first SYNACK scheduled the task. */ | ||
1086 | GNUNET_SCHEDULER_cancel (*task_id); | ||
1087 | } | ||
1088 | |||
1089 | /* Schedule the task */ | ||
1090 | *task_id = GNUNET_SCHEDULER_add_delayed (delay, keepalive_task, c); | ||
1091 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next keepalive in %s\n", | ||
1092 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * @brief Re-initiate traffic on this connection if necessary. | ||
1098 | * | ||
1099 | * Check if there is traffic queued towards this peer | ||
1100 | * and the core transmit handle is NULL (traffic was stalled). | ||
1101 | * If so, call core tmt rdy. | ||
1102 | * | ||
1103 | * @param c Connection on which initiate traffic. | ||
1104 | * @param fwd Is this about fwd traffic? | ||
1105 | */ | ||
1106 | static void | ||
1107 | connection_unlock_queue (struct CadetConnection *c, int fwd) | ||
1108 | { | ||
1109 | struct CadetPeer *peer; | ||
1110 | |||
1111 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1112 | "connection_unlock_queue %s on %s\n", | ||
1113 | GM_f2s (fwd), GMC_2s (c)); | ||
1114 | |||
1115 | if (GMC_is_terminal (c, fwd)) | ||
1116 | { | ||
1117 | LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n"); | ||
1118 | return; | ||
1119 | } | ||
1120 | |||
1121 | peer = get_hop (c, fwd); | ||
1122 | GMP_queue_unlock (peer, c); | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | /** | ||
1127 | * Cancel all transmissions that belong to a certain connection. | ||
1128 | * | ||
1129 | * If the connection is scheduled for destruction and no more messages are left, | ||
1130 | * the connection will be destroyed by the continuation call. | ||
1131 | * | ||
1132 | * @param c Connection which to cancel. Might be destroyed during this call. | ||
1133 | * @param fwd Cancel fwd traffic? | ||
1134 | */ | ||
1135 | static void | ||
1136 | connection_cancel_queues (struct CadetConnection *c, int fwd) | ||
1137 | { | ||
1138 | struct CadetFlowControl *fc; | ||
1139 | struct CadetPeer *peer; | ||
1140 | |||
1141 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1142 | " *** Cancel %s queues for connection %s\n", | ||
1143 | GM_f2s (fwd), GMC_2s (c)); | ||
1144 | if (NULL == c) | ||
1145 | { | ||
1146 | GNUNET_break (0); | ||
1147 | return; | ||
1148 | } | ||
1149 | |||
1150 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
1151 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) | ||
1152 | { | ||
1153 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
1154 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
1155 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc); | ||
1156 | } | ||
1157 | peer = get_hop (c, fwd); | ||
1158 | GMP_queue_cancel (peer, c); | ||
1159 | } | ||
1160 | |||
1161 | |||
1162 | /** | ||
1163 | * Function called if a connection has been stalled for a while, | ||
1164 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1165 | * | ||
1166 | * @param cls Closure (poll ctx). | ||
1167 | * @param tc TaskContext. | ||
1168 | */ | ||
1169 | static void | ||
1170 | connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Callback called when a queued POLL message is sent. | ||
1175 | * | ||
1176 | * @param cls Closure (FC). | ||
1177 | * @param c Connection this message was on. | ||
1178 | * @param q Queue handler this call invalidates. | ||
1179 | * @param type Type of message sent. | ||
1180 | * @param fwd Was this a FWD going message? | ||
1181 | * @param size Size of the message. | ||
1182 | */ | ||
1183 | static void | ||
1184 | poll_sent (void *cls, | ||
1185 | struct CadetConnection *c, | ||
1186 | struct CadetConnectionQueue *q, | ||
1187 | uint16_t type, int fwd, size_t size) | ||
1188 | { | ||
1189 | struct CadetFlowControl *fc = cls; | ||
1190 | |||
1191 | if (2 == c->destroy) | ||
1192 | { | ||
1193 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); | ||
1194 | return; | ||
1195 | } | ||
1196 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1197 | " *** POLL sent for , scheduling new one!\n"); | ||
1198 | fc->poll_msg = NULL; | ||
1199 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); | ||
1200 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
1201 | &connection_poll, fc); | ||
1202 | LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); | ||
1203 | |||
1204 | } | ||
1205 | |||
1206 | /** | ||
1207 | * Function called if a connection has been stalled for a while, | ||
1208 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1209 | * | ||
1210 | * @param cls Closure (poll ctx). | ||
1211 | * @param tc TaskContext. | ||
1212 | */ | ||
1213 | static void | ||
1214 | connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1215 | { | ||
1216 | struct CadetFlowControl *fc = cls; | ||
1217 | struct GNUNET_CADET_Poll msg; | ||
1218 | struct CadetConnection *c; | ||
1219 | |||
1220 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
1221 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1222 | { | ||
1223 | return; | ||
1224 | } | ||
1225 | |||
1226 | c = fc->c; | ||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling connection %s %s\n", | ||
1228 | GMC_2s (c), fc == &c->fwd_fc ? "FWD" : "BCK"); | ||
1229 | |||
1230 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL); | ||
1231 | msg.header.size = htons (sizeof (msg)); | ||
1232 | msg.pid = htonl (fc->last_pid_sent); | ||
1233 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent); | ||
1234 | fc->poll_msg = | ||
1235 | GMC_send_prebuilt_message (&msg.header, | ||
1236 | GNUNET_MESSAGE_TYPE_CADET_POLL, | ||
1237 | fc->last_pid_sent, | ||
1238 | c, fc == &c->fwd_fc, GNUNET_YES, | ||
1239 | &poll_sent, fc); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | /** | ||
1244 | * Timeout function due to lack of keepalive/traffic from the owner. | ||
1245 | * Destroys connection if called. | ||
1246 | * | ||
1247 | * @param cls Closure (connection to destroy). | ||
1248 | * @param tc TaskContext. | ||
1249 | */ | ||
1250 | static void | ||
1251 | connection_fwd_timeout (void *cls, | ||
1252 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1253 | { | ||
1254 | struct CadetConnection *c = cls; | ||
1255 | |||
1256 | c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
1257 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1258 | return; | ||
1259 | |||
1260 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s FWD timed out. Destroying.\n", | ||
1261 | GMC_2s (c)); | ||
1262 | if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */ | ||
1263 | { | ||
1264 | GNUNET_break (0); | ||
1265 | return; | ||
1266 | } | ||
1267 | |||
1268 | GMC_destroy (c); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | /** | ||
1273 | * Timeout function due to lack of keepalive/traffic from the destination. | ||
1274 | * Destroys connection if called. | ||
1275 | * | ||
1276 | * @param cls Closure (connection to destroy). | ||
1277 | * @param tc TaskContext | ||
1278 | */ | ||
1279 | static void | ||
1280 | connection_bck_timeout (void *cls, | ||
1281 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1282 | { | ||
1283 | struct CadetConnection *c = cls; | ||
1284 | |||
1285 | c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
1286 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1287 | return; | ||
1288 | |||
1289 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s BCK timed out. Destroying.\n", | ||
1290 | GMC_2s (c)); | ||
1291 | |||
1292 | if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */ | ||
1293 | { | ||
1294 | GNUNET_break (0); | ||
1295 | return; | ||
1296 | } | ||
1297 | |||
1298 | GMC_destroy (c); | ||
1299 | } | ||
1300 | |||
1301 | |||
1302 | /** | ||
1303 | * Resets the connection timeout task, some other message has done the | ||
1304 | * task's job. | ||
1305 | * - For the first peer on the direction this means to send | ||
1306 | * a keepalive or a path confirmation message (either create or ACK). | ||
1307 | * - For all other peers, this means to destroy the connection, | ||
1308 | * due to lack of activity. | ||
1309 | * Starts the timeout if no timeout was running (connection just created). | ||
1310 | * | ||
1311 | * @param c Connection whose timeout to reset. | ||
1312 | * @param fwd Is this forward? | ||
1313 | * | ||
1314 | * TODO use heap to improve efficiency of scheduler. | ||
1315 | */ | ||
1316 | static void | ||
1317 | connection_reset_timeout (struct CadetConnection *c, int fwd) | ||
1318 | { | ||
1319 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd)); | ||
1320 | |||
1321 | if (GMC_is_origin (c, fwd)) /* Startpoint */ | ||
1322 | { | ||
1323 | schedule_next_keepalive (c, fwd); | ||
1324 | } | ||
1325 | else /* Relay, endpoint. */ | ||
1326 | { | ||
1327 | struct GNUNET_TIME_Relative delay; | ||
1328 | GNUNET_SCHEDULER_TaskIdentifier *ti; | ||
1329 | GNUNET_SCHEDULER_Task f; | ||
1330 | |||
1331 | ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task; | ||
1332 | |||
1333 | if (GNUNET_SCHEDULER_NO_TASK != *ti) | ||
1334 | GNUNET_SCHEDULER_cancel (*ti); | ||
1335 | delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4); | ||
1336 | f = fwd ? &connection_fwd_timeout : &connection_bck_timeout; | ||
1337 | *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | /** | ||
1343 | * Add the connection to the list of both neighbors. | ||
1344 | * | ||
1345 | * @param c Connection. | ||
1346 | * | ||
1347 | * @return #GNUNET_OK if everything went fine | ||
1348 | * #GNUNET_SYSERR if the was an error and @c c is malformed. | ||
1349 | */ | ||
1350 | static int | ||
1351 | register_neighbors (struct CadetConnection *c) | ||
1352 | { | ||
1353 | struct CadetPeer *next_peer; | ||
1354 | struct CadetPeer *prev_peer; | ||
1355 | |||
1356 | next_peer = get_next_hop (c); | ||
1357 | prev_peer = get_prev_hop (c); | ||
1358 | |||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, "register neighbors for connection %s\n", | ||
1360 | GMC_2s (c)); | ||
1361 | path_debug (c->path); | ||
1362 | LOG (GNUNET_ERROR_TYPE_DEBUG, "own pos %u\n", c->own_pos); | ||
1363 | LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to next peer %p\n", | ||
1364 | GMC_2s (c), next_peer); | ||
1365 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", next_peer, GMP_2s (next_peer)); | ||
1366 | LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to prev peer %p\n", | ||
1367 | GMC_2s (c), prev_peer); | ||
1368 | LOG (GNUNET_ERROR_TYPE_DEBUG, "prev peer %p %s\n", prev_peer, GMP_2s (prev_peer)); | ||
1369 | |||
1370 | if (GNUNET_NO == GMP_is_neighbor (next_peer) | ||
1371 | || GNUNET_NO == GMP_is_neighbor (prev_peer)) | ||
1372 | { | ||
1373 | if (GMC_is_origin (c, GNUNET_YES)) | ||
1374 | GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO); | ||
1375 | GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO); | ||
1376 | |||
1377 | LOG (GNUNET_ERROR_TYPE_DEBUG, " register neighbors failed\n"); | ||
1378 | LOG (GNUNET_ERROR_TYPE_DEBUG, " prev: %s, neighbor?: %d\n", | ||
1379 | GMP_2s (prev_peer), GMP_is_neighbor (prev_peer)); | ||
1380 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next: %s, neighbor?: %d\n", | ||
1381 | GMP_2s (next_peer), GMP_is_neighbor (next_peer)); | ||
1382 | return GNUNET_SYSERR; | ||
1383 | } | ||
1384 | |||
1385 | GMP_add_connection (next_peer, c); | ||
1386 | GMP_add_connection (prev_peer, c); | ||
1387 | |||
1388 | return GNUNET_OK; | ||
1389 | } | ||
1390 | |||
1391 | |||
1392 | /** | ||
1393 | * Remove the connection from the list of both neighbors. | ||
1394 | * | ||
1395 | * @param c Connection. | ||
1396 | */ | ||
1397 | static void | ||
1398 | unregister_neighbors (struct CadetConnection *c) | ||
1399 | { | ||
1400 | struct CadetPeer *peer; | ||
1401 | |||
1402 | peer = get_next_hop (c); | ||
1403 | if (GNUNET_OK != GMP_remove_connection (peer, c)) | ||
1404 | { | ||
1405 | GNUNET_assert (CADET_CONNECTION_NEW == c->state | ||
1406 | || CADET_CONNECTION_DESTROYED == c->state); | ||
1407 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); | ||
1408 | if (NULL != c->t) GMT_debug (c->t); | ||
1409 | } | ||
1410 | |||
1411 | peer = get_prev_hop (c); | ||
1412 | if (GNUNET_OK != GMP_remove_connection (peer, c)) | ||
1413 | { | ||
1414 | GNUNET_assert (CADET_CONNECTION_NEW == c->state | ||
1415 | || CADET_CONNECTION_DESTROYED == c->state); | ||
1416 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); | ||
1417 | if (NULL != c->t) GMT_debug (c->t); | ||
1418 | } | ||
1419 | } | ||
1420 | |||
1421 | |||
1422 | /** | ||
1423 | * Bind the connection to the peer and the tunnel to that peer. | ||
1424 | * | ||
1425 | * If the peer has no tunnel, create one. Update tunnel and connection | ||
1426 | * data structres to reflect new status. | ||
1427 | * | ||
1428 | * @param c Connection. | ||
1429 | * @param peer Peer. | ||
1430 | */ | ||
1431 | static void | ||
1432 | add_to_peer (struct CadetConnection *c, struct CadetPeer *peer) | ||
1433 | { | ||
1434 | GMP_add_tunnel (peer); | ||
1435 | c->t = GMP_get_tunnel (peer); | ||
1436 | GMT_add_connection (c->t, c); | ||
1437 | } | ||
1438 | |||
1439 | |||
1440 | /** | ||
1441 | * Builds a path from a PeerIdentity array. | ||
1442 | * | ||
1443 | * @param peers PeerIdentity array. | ||
1444 | * @param size Size of the @c peers array. | ||
1445 | * @param own_pos Output parameter: own position in the path. | ||
1446 | * | ||
1447 | * @return Fixed and shortened path. | ||
1448 | */ | ||
1449 | static struct CadetPeerPath * | ||
1450 | build_path_from_peer_ids (struct GNUNET_PeerIdentity *peers, | ||
1451 | unsigned int size, | ||
1452 | unsigned int *own_pos) | ||
1453 | { | ||
1454 | struct CadetPeerPath *path; | ||
1455 | GNUNET_PEER_Id shortid; | ||
1456 | unsigned int i; | ||
1457 | unsigned int j; | ||
1458 | unsigned int offset; | ||
1459 | |||
1460 | /* Create path */ | ||
1461 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); | ||
1462 | path = path_new (size); | ||
1463 | *own_pos = 0; | ||
1464 | offset = 0; | ||
1465 | for (i = 0; i < size; i++) | ||
1466 | { | ||
1467 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n", | ||
1468 | i, GNUNET_i2s (&peers[i])); | ||
1469 | shortid = GNUNET_PEER_intern (&peers[i]); | ||
1470 | |||
1471 | /* Check for loops / duplicates */ | ||
1472 | for (j = 0; j < i - offset; j++) | ||
1473 | { | ||
1474 | if (path->peers[j] == shortid) | ||
1475 | { | ||
1476 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j); | ||
1477 | offset = i - j; | ||
1478 | LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset); | ||
1479 | GNUNET_PEER_change_rc (shortid, -1); | ||
1480 | } | ||
1481 | } | ||
1482 | LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset); | ||
1483 | path->peers[i - offset] = shortid; | ||
1484 | if (path->peers[i - offset] == myid) | ||
1485 | *own_pos = i - offset; | ||
1486 | } | ||
1487 | path->length -= offset; | ||
1488 | |||
1489 | if (path->peers[*own_pos] != myid) | ||
1490 | { | ||
1491 | /* create path: self not found in path through self */ | ||
1492 | GNUNET_break_op (0); | ||
1493 | path_destroy (path); | ||
1494 | return NULL; | ||
1495 | } | ||
1496 | |||
1497 | return path; | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | /** | ||
1502 | * Log receipt of message on stderr (INFO level). | ||
1503 | * | ||
1504 | * @param message Message received. | ||
1505 | * @param peer Peer who sent the message. | ||
1506 | * @param hash Connection ID. | ||
1507 | */ | ||
1508 | static void | ||
1509 | log_message (const struct GNUNET_MessageHeader *message, | ||
1510 | const struct GNUNET_PeerIdentity *peer, | ||
1511 | const struct GNUNET_CADET_Hash *hash) | ||
1512 | { | ||
1513 | LOG (GNUNET_ERROR_TYPE_INFO, "<-- %s on connection %s from %s\n", | ||
1514 | GM_m2s (ntohs (message->type)), GNUNET_h2s (GM_h2hc (hash)), | ||
1515 | GNUNET_i2s (peer)); | ||
1516 | } | ||
1517 | |||
1518 | /******************************************************************************/ | ||
1519 | /******************************** API ***********************************/ | ||
1520 | /******************************************************************************/ | ||
1521 | |||
1522 | /** | ||
1523 | * Core handler for connection creation. | ||
1524 | * | ||
1525 | * @param cls Closure (unused). | ||
1526 | * @param peer Sender (neighbor). | ||
1527 | * @param message Message. | ||
1528 | * | ||
1529 | * @return GNUNET_OK to keep the connection open, | ||
1530 | * GNUNET_SYSERR to close it (signal serious error) | ||
1531 | */ | ||
1532 | int | ||
1533 | GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1534 | const struct GNUNET_MessageHeader *message) | ||
1535 | { | ||
1536 | struct GNUNET_CADET_ConnectionCreate *msg; | ||
1537 | struct GNUNET_PeerIdentity *id; | ||
1538 | struct GNUNET_CADET_Hash *cid; | ||
1539 | struct CadetPeerPath *path; | ||
1540 | struct CadetPeer *dest_peer; | ||
1541 | struct CadetPeer *orig_peer; | ||
1542 | struct CadetConnection *c; | ||
1543 | unsigned int own_pos; | ||
1544 | uint16_t size; | ||
1545 | |||
1546 | /* Check size */ | ||
1547 | size = ntohs (message->size); | ||
1548 | if (size < sizeof (struct GNUNET_CADET_ConnectionCreate)) | ||
1549 | { | ||
1550 | GNUNET_break_op (0); | ||
1551 | return GNUNET_OK; | ||
1552 | } | ||
1553 | |||
1554 | /* Calculate hops */ | ||
1555 | size -= sizeof (struct GNUNET_CADET_ConnectionCreate); | ||
1556 | if (size % sizeof (struct GNUNET_PeerIdentity)) | ||
1557 | { | ||
1558 | GNUNET_break_op (0); | ||
1559 | return GNUNET_OK; | ||
1560 | } | ||
1561 | size /= sizeof (struct GNUNET_PeerIdentity); | ||
1562 | if (1 > size) | ||
1563 | { | ||
1564 | GNUNET_break_op (0); | ||
1565 | return GNUNET_OK; | ||
1566 | } | ||
1567 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); | ||
1568 | |||
1569 | /* Get parameters */ | ||
1570 | msg = (struct GNUNET_CADET_ConnectionCreate *) message; | ||
1571 | cid = &msg->cid; | ||
1572 | log_message (message, peer, cid); | ||
1573 | id = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1574 | LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id)); | ||
1575 | |||
1576 | /* Create connection */ | ||
1577 | c = connection_get (cid); | ||
1578 | if (NULL == c) | ||
1579 | { | ||
1580 | path = build_path_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1], | ||
1581 | size, &own_pos); | ||
1582 | if (NULL == path) | ||
1583 | return GNUNET_OK; | ||
1584 | if (0 == own_pos) | ||
1585 | { | ||
1586 | GNUNET_break_op (0); | ||
1587 | path_destroy (path); | ||
1588 | return GNUNET_OK; | ||
1589 | } | ||
1590 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); | ||
1591 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); | ||
1592 | c = GMC_new (cid, NULL, path_duplicate (path), own_pos); | ||
1593 | if (NULL == c) | ||
1594 | { | ||
1595 | if (path->length - 1 == own_pos) | ||
1596 | { | ||
1597 | /* If we are destination, why did the creation fail? */ | ||
1598 | GNUNET_break (0); | ||
1599 | return GNUNET_OK; | ||
1600 | } | ||
1601 | send_broken_unknown (cid, &my_full_id, | ||
1602 | GNUNET_PEER_resolve2 (path->peers[own_pos + 1]), | ||
1603 | peer); | ||
1604 | path_destroy (path); | ||
1605 | return GNUNET_OK; | ||
1606 | } | ||
1607 | GMP_add_path_to_all (path, GNUNET_NO); | ||
1608 | connection_reset_timeout (c, GNUNET_YES); | ||
1609 | } | ||
1610 | else | ||
1611 | { | ||
1612 | path = path_duplicate (c->path); | ||
1613 | } | ||
1614 | if (CADET_CONNECTION_NEW == c->state) | ||
1615 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
1616 | |||
1617 | /* Remember peers */ | ||
1618 | dest_peer = GMP_get (&id[size - 1]); | ||
1619 | orig_peer = GMP_get (&id[0]); | ||
1620 | |||
1621 | /* Is it a connection to us? */ | ||
1622 | if (c->own_pos == path->length - 1) | ||
1623 | { | ||
1624 | LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); | ||
1625 | GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); | ||
1626 | |||
1627 | add_to_peer (c, orig_peer); | ||
1628 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (c->t)) | ||
1629 | GMT_change_cstate (c->t, CADET_TUNNEL3_WAITING); | ||
1630 | |||
1631 | send_connection_ack (c, GNUNET_NO); | ||
1632 | if (CADET_CONNECTION_SENT == c->state) | ||
1633 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
1634 | } | ||
1635 | else | ||
1636 | { | ||
1637 | /* It's for somebody else! Retransmit. */ | ||
1638 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); | ||
1639 | GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); | ||
1640 | GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); | ||
1641 | GMC_send_prebuilt_message (message, | ||
1642 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0, | ||
1643 | c, GNUNET_YES, GNUNET_YES, | ||
1644 | NULL, NULL); | ||
1645 | } | ||
1646 | path_destroy (path); | ||
1647 | return GNUNET_OK; | ||
1648 | } | ||
1649 | |||
1650 | |||
1651 | /** | ||
1652 | * Core handler for path confirmations. | ||
1653 | * | ||
1654 | * @param cls closure | ||
1655 | * @param message message | ||
1656 | * @param peer peer identity this notification is about | ||
1657 | * | ||
1658 | * @return GNUNET_OK to keep the connection open, | ||
1659 | * GNUNET_SYSERR to close it (signal serious error) | ||
1660 | */ | ||
1661 | int | ||
1662 | GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1663 | const struct GNUNET_MessageHeader *message) | ||
1664 | { | ||
1665 | struct GNUNET_CADET_ConnectionACK *msg; | ||
1666 | struct CadetConnection *c; | ||
1667 | struct CadetPeerPath *p; | ||
1668 | struct CadetPeer *pi; | ||
1669 | enum CadetConnectionState oldstate; | ||
1670 | int fwd; | ||
1671 | |||
1672 | msg = (struct GNUNET_CADET_ConnectionACK *) message; | ||
1673 | log_message (message, peer, &msg->cid); | ||
1674 | c = connection_get (&msg->cid); | ||
1675 | if (NULL == c) | ||
1676 | { | ||
1677 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
1678 | 1, GNUNET_NO); | ||
1679 | LOG (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n"); | ||
1680 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
1681 | return GNUNET_OK; | ||
1682 | } | ||
1683 | |||
1684 | if (GNUNET_NO != c->destroy) | ||
1685 | { | ||
1686 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection being destroyed\n"); | ||
1687 | return GNUNET_OK; | ||
1688 | } | ||
1689 | |||
1690 | oldstate = c->state; | ||
1691 | LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer)); | ||
1692 | pi = GMP_get (peer); | ||
1693 | if (get_next_hop (c) == pi) | ||
1694 | { | ||
1695 | LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); | ||
1696 | fwd = GNUNET_NO; | ||
1697 | if (CADET_CONNECTION_SENT == oldstate) | ||
1698 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
1699 | } | ||
1700 | else if (get_prev_hop (c) == pi) | ||
1701 | { | ||
1702 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK\n"); | ||
1703 | fwd = GNUNET_YES; | ||
1704 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1705 | } | ||
1706 | else | ||
1707 | { | ||
1708 | GNUNET_break_op (0); | ||
1709 | return GNUNET_OK; | ||
1710 | } | ||
1711 | |||
1712 | connection_reset_timeout (c, fwd); | ||
1713 | |||
1714 | /* Add path to peers? */ | ||
1715 | p = c->path; | ||
1716 | if (NULL != p) | ||
1717 | { | ||
1718 | GMP_add_path_to_all (p, GNUNET_YES); | ||
1719 | } | ||
1720 | else | ||
1721 | { | ||
1722 | GNUNET_break (0); | ||
1723 | } | ||
1724 | |||
1725 | /* Message for us as creator? */ | ||
1726 | if (GMC_is_origin (c, GNUNET_YES)) | ||
1727 | { | ||
1728 | if (GNUNET_NO != fwd) | ||
1729 | { | ||
1730 | GNUNET_break_op (0); | ||
1731 | return GNUNET_OK; | ||
1732 | } | ||
1733 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); | ||
1734 | |||
1735 | /* If just created, cancel the short timeout and start a long one */ | ||
1736 | if (CADET_CONNECTION_SENT == oldstate) | ||
1737 | connection_reset_timeout (c, GNUNET_YES); | ||
1738 | |||
1739 | /* Change connection state */ | ||
1740 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1741 | send_connection_ack (c, GNUNET_YES); | ||
1742 | |||
1743 | /* Change tunnel state, trigger KX */ | ||
1744 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
1745 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
1746 | |||
1747 | return GNUNET_OK; | ||
1748 | } | ||
1749 | |||
1750 | /* Message for us as destination? */ | ||
1751 | if (GMC_is_terminal (c, GNUNET_YES)) | ||
1752 | { | ||
1753 | if (GNUNET_YES != fwd) | ||
1754 | { | ||
1755 | GNUNET_break_op (0); | ||
1756 | return GNUNET_OK; | ||
1757 | } | ||
1758 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); | ||
1759 | |||
1760 | /* If just created, cancel the short timeout and start a long one */ | ||
1761 | if (CADET_CONNECTION_ACK == oldstate) | ||
1762 | connection_reset_timeout (c, GNUNET_NO); | ||
1763 | |||
1764 | /* Change tunnel state */ | ||
1765 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
1766 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
1767 | |||
1768 | return GNUNET_OK; | ||
1769 | } | ||
1770 | |||
1771 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
1772 | GMC_send_prebuilt_message (message, | ||
1773 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0, | ||
1774 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1775 | return GNUNET_OK; | ||
1776 | } | ||
1777 | |||
1778 | |||
1779 | /** | ||
1780 | * Core handler for notifications of broken connections. | ||
1781 | * | ||
1782 | * @param cls Closure (unused). | ||
1783 | * @param id Peer identity of sending neighbor. | ||
1784 | * @param message Message. | ||
1785 | * | ||
1786 | * @return GNUNET_OK to keep the connection open, | ||
1787 | * GNUNET_SYSERR to close it (signal serious error) | ||
1788 | */ | ||
1789 | int | ||
1790 | GMC_handle_broken (void* cls, | ||
1791 | const struct GNUNET_PeerIdentity* id, | ||
1792 | const struct GNUNET_MessageHeader* message) | ||
1793 | { | ||
1794 | struct GNUNET_CADET_ConnectionBroken *msg; | ||
1795 | struct CadetConnection *c; | ||
1796 | int fwd; | ||
1797 | |||
1798 | msg = (struct GNUNET_CADET_ConnectionBroken *) message; | ||
1799 | log_message (message, id, &msg->cid); | ||
1800 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", | ||
1801 | GNUNET_i2s (&msg->peer1)); | ||
1802 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", | ||
1803 | GNUNET_i2s (&msg->peer2)); | ||
1804 | c = connection_get (&msg->cid); | ||
1805 | if (NULL == c) | ||
1806 | { | ||
1807 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n"); | ||
1808 | return GNUNET_OK; | ||
1809 | } | ||
1810 | |||
1811 | fwd = is_fwd (c, id); | ||
1812 | if (GMC_is_terminal (c, fwd)) | ||
1813 | { | ||
1814 | struct GNUNET_MessageHeader *out_msg; | ||
1815 | struct CadetPeer *neighbor; | ||
1816 | struct CadetPeer *endpoint; | ||
1817 | |||
1818 | neighbor = get_hop (c, !fwd); | ||
1819 | endpoint = GMP_get_short (c->path->peers[c->path->length - 1]); | ||
1820 | path_invalidate (c->path); | ||
1821 | GMP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); | ||
1822 | c->state = CADET_CONNECTION_DESTROYED; | ||
1823 | while (NULL != (out_msg = GMP_connection_pop (neighbor, c))) | ||
1824 | { | ||
1825 | GNUNET_assert (NULL == | ||
1826 | GMT_send_prebuilt_message (out_msg, c->t, NULL, GNUNET_YES, | ||
1827 | NULL, NULL)); | ||
1828 | } | ||
1829 | |||
1830 | GMC_destroy (c); | ||
1831 | } | ||
1832 | else | ||
1833 | { | ||
1834 | GMC_send_prebuilt_message (message, | ||
1835 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0, | ||
1836 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1837 | c->destroy = GNUNET_YES; | ||
1838 | connection_cancel_queues (c, !fwd); | ||
1839 | } | ||
1840 | |||
1841 | return GNUNET_OK; | ||
1842 | |||
1843 | } | ||
1844 | |||
1845 | |||
1846 | /** | ||
1847 | * Core handler for tunnel destruction | ||
1848 | * | ||
1849 | * @param cls Closure (unused). | ||
1850 | * @param peer Peer identity of sending neighbor. | ||
1851 | * @param message Message. | ||
1852 | * | ||
1853 | * @return GNUNET_OK to keep the connection open, | ||
1854 | * GNUNET_SYSERR to close it (signal serious error) | ||
1855 | */ | ||
1856 | int | ||
1857 | GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1858 | const struct GNUNET_MessageHeader *message) | ||
1859 | { | ||
1860 | struct GNUNET_CADET_ConnectionDestroy *msg; | ||
1861 | struct CadetConnection *c; | ||
1862 | int fwd; | ||
1863 | |||
1864 | msg = (struct GNUNET_CADET_ConnectionDestroy *) message; | ||
1865 | log_message (message, peer, &msg->cid); | ||
1866 | c = connection_get (&msg->cid); | ||
1867 | if (NULL == c) | ||
1868 | { | ||
1869 | /* Probably already got the message from another path, | ||
1870 | * destroyed the tunnel and retransmitted to children. | ||
1871 | * Safe to ignore. | ||
1872 | */ | ||
1873 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
1874 | 1, GNUNET_NO); | ||
1875 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection unknown: already destroyed?\n"); | ||
1876 | return GNUNET_OK; | ||
1877 | } | ||
1878 | fwd = is_fwd (c, peer); | ||
1879 | if (GNUNET_SYSERR == fwd) | ||
1880 | { | ||
1881 | GNUNET_break_op (0); /* FIXME */ | ||
1882 | return GNUNET_OK; | ||
1883 | } | ||
1884 | if (GNUNET_NO == GMC_is_terminal (c, fwd)) | ||
1885 | GMC_send_prebuilt_message (message, | ||
1886 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
1887 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1888 | else if (0 == c->pending_messages) | ||
1889 | { | ||
1890 | LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); | ||
1891 | GMC_destroy (c); | ||
1892 | return GNUNET_OK; | ||
1893 | } | ||
1894 | c->destroy = GNUNET_YES; | ||
1895 | c->state = CADET_CONNECTION_DESTROYED; | ||
1896 | if (NULL != c->t) | ||
1897 | { | ||
1898 | GMT_remove_connection (c->t, c); | ||
1899 | c->t = NULL; | ||
1900 | } | ||
1901 | |||
1902 | return GNUNET_OK; | ||
1903 | } | ||
1904 | |||
1905 | /** | ||
1906 | * Generic handler for cadet network encrypted traffic. | ||
1907 | * | ||
1908 | * @param peer Peer identity this notification is about. | ||
1909 | * @param msg Encrypted message. | ||
1910 | * | ||
1911 | * @return GNUNET_OK to keep the connection open, | ||
1912 | * GNUNET_SYSERR to close it (signal serious error) | ||
1913 | */ | ||
1914 | static int | ||
1915 | handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer, | ||
1916 | const struct GNUNET_CADET_Encrypted *msg) | ||
1917 | { | ||
1918 | struct CadetConnection *c; | ||
1919 | struct CadetPeer *neighbor; | ||
1920 | struct CadetFlowControl *fc; | ||
1921 | GNUNET_PEER_Id peer_id; | ||
1922 | uint32_t pid; | ||
1923 | uint32_t ttl; | ||
1924 | size_t size; | ||
1925 | int fwd; | ||
1926 | |||
1927 | log_message (&msg->header, peer, &msg->cid); | ||
1928 | |||
1929 | /* Check size */ | ||
1930 | size = ntohs (msg->header.size); | ||
1931 | if (size < | ||
1932 | sizeof (struct GNUNET_CADET_Encrypted) + | ||
1933 | sizeof (struct GNUNET_MessageHeader)) | ||
1934 | { | ||
1935 | GNUNET_break_op (0); | ||
1936 | return GNUNET_OK; | ||
1937 | } | ||
1938 | |||
1939 | /* Check connection */ | ||
1940 | c = connection_get (&msg->cid); | ||
1941 | if (NULL == c) | ||
1942 | { | ||
1943 | GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); | ||
1944 | LOG (GNUNET_ERROR_TYPE_DEBUG, "enc on unknown connection %s\n", | ||
1945 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
1946 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
1947 | return GNUNET_OK; | ||
1948 | } | ||
1949 | |||
1950 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s\n", GMC_2s (c)); | ||
1951 | |||
1952 | /* Check if origin is as expected */ | ||
1953 | neighbor = get_prev_hop (c); | ||
1954 | peer_id = GNUNET_PEER_search (peer); | ||
1955 | if (peer_id == GMP_get_short_id (neighbor)) | ||
1956 | { | ||
1957 | fwd = GNUNET_YES; | ||
1958 | } | ||
1959 | else | ||
1960 | { | ||
1961 | neighbor = get_next_hop (c); | ||
1962 | if (peer_id == GMP_get_short_id (neighbor)) | ||
1963 | { | ||
1964 | fwd = GNUNET_NO; | ||
1965 | } | ||
1966 | else | ||
1967 | { | ||
1968 | /* Unexpected peer sending traffic on a connection. */ | ||
1969 | GNUNET_break_op (0); | ||
1970 | return GNUNET_OK; | ||
1971 | } | ||
1972 | } | ||
1973 | |||
1974 | /* Check PID */ | ||
1975 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
1976 | pid = ntohl (msg->pid); | ||
1977 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n", | ||
1978 | pid, fc->last_pid_recv + 1); | ||
1979 | if (GM_is_pid_bigger (pid, fc->last_ack_sent)) | ||
1980 | { | ||
1981 | GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); | ||
1982 | GNUNET_break_op (0); | ||
1983 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1984 | "Received PID %u, (prev %u), ACK %u\n", | ||
1985 | pid, fc->last_pid_recv, fc->last_ack_sent); | ||
1986 | return GNUNET_OK; | ||
1987 | } | ||
1988 | if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv)) | ||
1989 | { | ||
1990 | GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); | ||
1991 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1992 | " PID %u not expected (%u+), dropping!\n", | ||
1993 | pid, fc->last_pid_recv + 1); | ||
1994 | return GNUNET_OK; | ||
1995 | } | ||
1996 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) | ||
1997 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1998 | connection_reset_timeout (c, fwd); | ||
1999 | fc->last_pid_recv = pid; | ||
2000 | |||
2001 | /* Is this message for us? */ | ||
2002 | if (GMC_is_terminal (c, fwd)) | ||
2003 | { | ||
2004 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | ||
2005 | GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); | ||
2006 | |||
2007 | if (NULL == c->t) | ||
2008 | { | ||
2009 | GNUNET_break (GNUNET_NO != c->destroy); | ||
2010 | return GNUNET_OK; | ||
2011 | } | ||
2012 | fc->last_pid_recv = pid; | ||
2013 | GMT_handle_encrypted (c->t, msg); | ||
2014 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
2015 | return GNUNET_OK; | ||
2016 | } | ||
2017 | |||
2018 | /* Message not for us: forward to next hop */ | ||
2019 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2020 | ttl = ntohl (msg->ttl); | ||
2021 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); | ||
2022 | if (ttl == 0) | ||
2023 | { | ||
2024 | GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); | ||
2025 | LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); | ||
2026 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
2027 | return GNUNET_OK; | ||
2028 | } | ||
2029 | |||
2030 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2031 | GMC_send_prebuilt_message (&msg->header, | ||
2032 | GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0, | ||
2033 | c, fwd, GNUNET_NO, NULL, NULL); | ||
2034 | |||
2035 | return GNUNET_OK; | ||
2036 | } | ||
2037 | |||
2038 | /** | ||
2039 | * Generic handler for cadet network encrypted traffic. | ||
2040 | * | ||
2041 | * @param peer Peer identity this notification is about. | ||
2042 | * @param msg Encrypted message. | ||
2043 | * | ||
2044 | * @return GNUNET_OK to keep the connection open, | ||
2045 | * GNUNET_SYSERR to close it (signal serious error) | ||
2046 | */ | ||
2047 | static int | ||
2048 | handle_cadet_kx (const struct GNUNET_PeerIdentity *peer, | ||
2049 | const struct GNUNET_CADET_KX *msg) | ||
2050 | { | ||
2051 | struct CadetConnection *c; | ||
2052 | struct CadetPeer *neighbor; | ||
2053 | GNUNET_PEER_Id peer_id; | ||
2054 | size_t size; | ||
2055 | int fwd; | ||
2056 | |||
2057 | log_message (&msg->header, peer, &msg->cid); | ||
2058 | |||
2059 | /* Check size */ | ||
2060 | size = ntohs (msg->header.size); | ||
2061 | if (size < | ||
2062 | sizeof (struct GNUNET_CADET_KX) + | ||
2063 | sizeof (struct GNUNET_MessageHeader)) | ||
2064 | { | ||
2065 | GNUNET_break_op (0); | ||
2066 | return GNUNET_OK; | ||
2067 | } | ||
2068 | |||
2069 | /* Check connection */ | ||
2070 | c = connection_get (&msg->cid); | ||
2071 | if (NULL == c) | ||
2072 | { | ||
2073 | GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); | ||
2074 | LOG (GNUNET_ERROR_TYPE_DEBUG, "kx on unknown connection %s\n", | ||
2075 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
2076 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2077 | return GNUNET_OK; | ||
2078 | } | ||
2079 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c)); | ||
2080 | |||
2081 | /* Check if origin is as expected */ | ||
2082 | neighbor = get_prev_hop (c); | ||
2083 | peer_id = GNUNET_PEER_search (peer); | ||
2084 | if (peer_id == GMP_get_short_id (neighbor)) | ||
2085 | { | ||
2086 | fwd = GNUNET_YES; | ||
2087 | } | ||
2088 | else | ||
2089 | { | ||
2090 | neighbor = get_next_hop (c); | ||
2091 | if (peer_id == GMP_get_short_id (neighbor)) | ||
2092 | { | ||
2093 | fwd = GNUNET_NO; | ||
2094 | } | ||
2095 | else | ||
2096 | { | ||
2097 | /* Unexpected peer sending traffic on a connection. */ | ||
2098 | GNUNET_break_op (0); | ||
2099 | return GNUNET_OK; | ||
2100 | } | ||
2101 | } | ||
2102 | |||
2103 | /* Count as connection confirmation. */ | ||
2104 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) | ||
2105 | { | ||
2106 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2107 | if (NULL != c->t) | ||
2108 | { | ||
2109 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
2110 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
2111 | } | ||
2112 | } | ||
2113 | connection_reset_timeout (c, fwd); | ||
2114 | |||
2115 | /* Is this message for us? */ | ||
2116 | if (GMC_is_terminal (c, fwd)) | ||
2117 | { | ||
2118 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | ||
2119 | GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); | ||
2120 | if (NULL == c->t) | ||
2121 | { | ||
2122 | GNUNET_break (0); | ||
2123 | return GNUNET_OK; | ||
2124 | } | ||
2125 | GMT_handle_kx (c->t, &msg[1].header); | ||
2126 | return GNUNET_OK; | ||
2127 | } | ||
2128 | |||
2129 | /* Message not for us: forward to next hop */ | ||
2130 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2131 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2132 | GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX, 0, | ||
2133 | c, fwd, GNUNET_NO, NULL, NULL); | ||
2134 | |||
2135 | return GNUNET_OK; | ||
2136 | } | ||
2137 | |||
2138 | |||
2139 | /** | ||
2140 | * Core handler for encrypted cadet network traffic (channel mgmt, data). | ||
2141 | * | ||
2142 | * @param cls Closure (unused). | ||
2143 | * @param message Message received. | ||
2144 | * @param peer Peer who sent the message. | ||
2145 | * | ||
2146 | * @return GNUNET_OK to keep the connection open, | ||
2147 | * GNUNET_SYSERR to close it (signal serious error) | ||
2148 | */ | ||
2149 | int | ||
2150 | GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2151 | const struct GNUNET_MessageHeader *message) | ||
2152 | { | ||
2153 | return handle_cadet_encrypted (peer, | ||
2154 | (struct GNUNET_CADET_Encrypted *)message); | ||
2155 | } | ||
2156 | |||
2157 | |||
2158 | /** | ||
2159 | * Core handler for key exchange traffic (ephemeral key, ping, pong). | ||
2160 | * | ||
2161 | * @param cls Closure (unused). | ||
2162 | * @param message Message received. | ||
2163 | * @param peer Peer who sent the message. | ||
2164 | * | ||
2165 | * @return GNUNET_OK to keep the connection open, | ||
2166 | * GNUNET_SYSERR to close it (signal serious error) | ||
2167 | */ | ||
2168 | int | ||
2169 | GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2170 | const struct GNUNET_MessageHeader *message) | ||
2171 | { | ||
2172 | return handle_cadet_kx (peer, | ||
2173 | (struct GNUNET_CADET_KX *) message); | ||
2174 | } | ||
2175 | |||
2176 | |||
2177 | /** | ||
2178 | * Core handler for cadet network traffic point-to-point acks. | ||
2179 | * | ||
2180 | * @param cls closure | ||
2181 | * @param message message | ||
2182 | * @param peer peer identity this notification is about | ||
2183 | * | ||
2184 | * @return GNUNET_OK to keep the connection open, | ||
2185 | * GNUNET_SYSERR to close it (signal serious error) | ||
2186 | */ | ||
2187 | int | ||
2188 | GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2189 | const struct GNUNET_MessageHeader *message) | ||
2190 | { | ||
2191 | struct GNUNET_CADET_ACK *msg; | ||
2192 | struct CadetConnection *c; | ||
2193 | struct CadetFlowControl *fc; | ||
2194 | GNUNET_PEER_Id id; | ||
2195 | uint32_t ack; | ||
2196 | int fwd; | ||
2197 | |||
2198 | msg = (struct GNUNET_CADET_ACK *) message; | ||
2199 | log_message (message, peer, &msg->cid); | ||
2200 | c = connection_get (&msg->cid); | ||
2201 | if (NULL == c) | ||
2202 | { | ||
2203 | GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, | ||
2204 | GNUNET_NO); | ||
2205 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2206 | return GNUNET_OK; | ||
2207 | } | ||
2208 | |||
2209 | /* Is this a forward or backward ACK? */ | ||
2210 | id = GNUNET_PEER_search (peer); | ||
2211 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
2212 | { | ||
2213 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); | ||
2214 | fc = &c->fwd_fc; | ||
2215 | fwd = GNUNET_YES; | ||
2216 | } | ||
2217 | else if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
2218 | { | ||
2219 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); | ||
2220 | fc = &c->bck_fc; | ||
2221 | fwd = GNUNET_NO; | ||
2222 | } | ||
2223 | else | ||
2224 | { | ||
2225 | GNUNET_break_op (0); | ||
2226 | return GNUNET_OK; | ||
2227 | } | ||
2228 | |||
2229 | ack = ntohl (msg->ack); | ||
2230 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", | ||
2231 | ack, fc->last_ack_recv); | ||
2232 | if (GM_is_pid_bigger (ack, fc->last_ack_recv)) | ||
2233 | fc->last_ack_recv = ack; | ||
2234 | |||
2235 | /* Cancel polling if the ACK is big enough. */ | ||
2236 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task && | ||
2237 | GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) | ||
2238 | { | ||
2239 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); | ||
2240 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
2241 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
2242 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
2243 | } | ||
2244 | |||
2245 | connection_unlock_queue (c, fwd); | ||
2246 | |||
2247 | return GNUNET_OK; | ||
2248 | } | ||
2249 | |||
2250 | |||
2251 | /** | ||
2252 | * Core handler for cadet network traffic point-to-point ack polls. | ||
2253 | * | ||
2254 | * @param cls closure | ||
2255 | * @param message message | ||
2256 | * @param peer peer identity this notification is about | ||
2257 | * | ||
2258 | * @return GNUNET_OK to keep the connection open, | ||
2259 | * GNUNET_SYSERR to close it (signal serious error) | ||
2260 | */ | ||
2261 | int | ||
2262 | GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2263 | const struct GNUNET_MessageHeader *message) | ||
2264 | { | ||
2265 | struct GNUNET_CADET_Poll *msg; | ||
2266 | struct CadetConnection *c; | ||
2267 | struct CadetFlowControl *fc; | ||
2268 | GNUNET_PEER_Id id; | ||
2269 | uint32_t pid; | ||
2270 | int fwd; | ||
2271 | |||
2272 | msg = (struct GNUNET_CADET_Poll *) message; | ||
2273 | log_message (message, peer, &msg->cid); | ||
2274 | c = connection_get (&msg->cid); | ||
2275 | if (NULL == c) | ||
2276 | { | ||
2277 | GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, | ||
2278 | GNUNET_NO); | ||
2279 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n", | ||
2280 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
2281 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2282 | return GNUNET_OK; | ||
2283 | } | ||
2284 | |||
2285 | /* Is this a forward or backward ACK? | ||
2286 | * Note: a poll should never be needed in a loopback case, | ||
2287 | * since there is no possiblility of packet loss there, so | ||
2288 | * this way of discerining FWD/BCK should not be a problem. | ||
2289 | */ | ||
2290 | id = GNUNET_PEER_search (peer); | ||
2291 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
2292 | { | ||
2293 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
2294 | fc = &c->fwd_fc; | ||
2295 | } | ||
2296 | else if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
2297 | { | ||
2298 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
2299 | fc = &c->bck_fc; | ||
2300 | } | ||
2301 | else | ||
2302 | { | ||
2303 | GNUNET_break_op (0); | ||
2304 | return GNUNET_OK; | ||
2305 | } | ||
2306 | |||
2307 | pid = ntohl (msg->pid); | ||
2308 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", pid, fc->last_pid_recv); | ||
2309 | fc->last_pid_recv = pid; | ||
2310 | fwd = fc == &c->bck_fc; | ||
2311 | GMC_send_ack (c, fwd, GNUNET_YES); | ||
2312 | |||
2313 | return GNUNET_OK; | ||
2314 | } | ||
2315 | |||
2316 | |||
2317 | /** | ||
2318 | * Send an ACK on the appropriate connection/channel, depending on | ||
2319 | * the direction and the position of the peer. | ||
2320 | * | ||
2321 | * @param c Which connection to send the hop-by-hop ACK. | ||
2322 | * @param fwd Is this a fwd ACK? (will go dest->root). | ||
2323 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | ||
2324 | */ | ||
2325 | void | ||
2326 | GMC_send_ack (struct CadetConnection *c, int fwd, int force) | ||
2327 | { | ||
2328 | unsigned int buffer; | ||
2329 | |||
2330 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2331 | "GMC send %s ACK on %s\n", | ||
2332 | GM_f2s (fwd), GMC_2s (c)); | ||
2333 | |||
2334 | if (NULL == c) | ||
2335 | { | ||
2336 | GNUNET_break (0); | ||
2337 | return; | ||
2338 | } | ||
2339 | |||
2340 | if (GNUNET_NO != c->destroy) | ||
2341 | { | ||
2342 | LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); | ||
2343 | return; | ||
2344 | } | ||
2345 | |||
2346 | /* Get available buffer space */ | ||
2347 | if (GMC_is_terminal (c, fwd)) | ||
2348 | { | ||
2349 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); | ||
2350 | buffer = GMT_get_channels_buffer (c->t); | ||
2351 | } | ||
2352 | else | ||
2353 | { | ||
2354 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n"); | ||
2355 | buffer = GMC_get_buffer (c, fwd); | ||
2356 | } | ||
2357 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); | ||
2358 | if (0 == buffer && GNUNET_NO == force) | ||
2359 | return; | ||
2360 | |||
2361 | /* Send available buffer space */ | ||
2362 | if (GMC_is_origin (c, fwd)) | ||
2363 | { | ||
2364 | GNUNET_assert (NULL != c->t); | ||
2365 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n"); | ||
2366 | GMT_unchoke_channels (c->t); | ||
2367 | } | ||
2368 | else | ||
2369 | { | ||
2370 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); | ||
2371 | send_ack (c, buffer, fwd, force); | ||
2372 | } | ||
2373 | } | ||
2374 | |||
2375 | |||
2376 | /** | ||
2377 | * Initialize the connections subsystem | ||
2378 | * | ||
2379 | * @param c Configuration handle. | ||
2380 | */ | ||
2381 | void | ||
2382 | GMC_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
2383 | { | ||
2384 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
2385 | if (GNUNET_OK != | ||
2386 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE", | ||
2387 | &max_msgs_queue)) | ||
2388 | { | ||
2389 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2390 | "CADET", "MAX_MSGS_QUEUE", "MISSING"); | ||
2391 | GNUNET_SCHEDULER_shutdown (); | ||
2392 | return; | ||
2393 | } | ||
2394 | |||
2395 | if (GNUNET_OK != | ||
2396 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS", | ||
2397 | &max_connections)) | ||
2398 | { | ||
2399 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2400 | "CADET", "MAX_CONNECTIONS", "MISSING"); | ||
2401 | GNUNET_SCHEDULER_shutdown (); | ||
2402 | return; | ||
2403 | } | ||
2404 | |||
2405 | if (GNUNET_OK != | ||
2406 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME", | ||
2407 | &refresh_connection_time)) | ||
2408 | { | ||
2409 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2410 | "CADET", "REFRESH_CONNECTION_TIME", "MISSING"); | ||
2411 | GNUNET_SCHEDULER_shutdown (); | ||
2412 | return; | ||
2413 | } | ||
2414 | create_connection_time = GNUNET_TIME_UNIT_SECONDS; | ||
2415 | connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); | ||
2416 | } | ||
2417 | |||
2418 | |||
2419 | /** | ||
2420 | * Destroy each connection on shutdown. | ||
2421 | * | ||
2422 | * @param cls Closure (unused). | ||
2423 | * @param key Current key code (CID, unused). | ||
2424 | * @param value Value in the hash map (connection) | ||
2425 | * | ||
2426 | * @return #GNUNET_YES, because we should continue to iterate, | ||
2427 | */ | ||
2428 | static int | ||
2429 | shutdown_iterator (void *cls, | ||
2430 | const struct GNUNET_HashCode *key, | ||
2431 | void *value) | ||
2432 | { | ||
2433 | struct CadetConnection *c = value; | ||
2434 | |||
2435 | GMC_destroy (c); | ||
2436 | return GNUNET_YES; | ||
2437 | } | ||
2438 | |||
2439 | |||
2440 | /** | ||
2441 | * Shut down the connections subsystem. | ||
2442 | */ | ||
2443 | void | ||
2444 | GMC_shutdown (void) | ||
2445 | { | ||
2446 | GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL); | ||
2447 | GNUNET_CONTAINER_multihashmap_destroy (connections); | ||
2448 | connections = NULL; | ||
2449 | } | ||
2450 | |||
2451 | |||
2452 | struct CadetConnection * | ||
2453 | GMC_new (const struct GNUNET_CADET_Hash *cid, | ||
2454 | struct CadetTunnel3 *t, | ||
2455 | struct CadetPeerPath *p, | ||
2456 | unsigned int own_pos) | ||
2457 | { | ||
2458 | struct CadetConnection *c; | ||
2459 | |||
2460 | c = GNUNET_new (struct CadetConnection); | ||
2461 | c->id = *cid; | ||
2462 | GNUNET_assert (GNUNET_OK == | ||
2463 | GNUNET_CONTAINER_multihashmap_put (connections, | ||
2464 | GMC_get_h (c), c, | ||
2465 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2466 | fc_init (&c->fwd_fc); | ||
2467 | fc_init (&c->bck_fc); | ||
2468 | c->fwd_fc.c = c; | ||
2469 | c->bck_fc.c = c; | ||
2470 | |||
2471 | c->t = t; | ||
2472 | GNUNET_assert (own_pos <= p->length - 1); | ||
2473 | c->own_pos = own_pos; | ||
2474 | c->path = p; | ||
2475 | p->c = c; | ||
2476 | |||
2477 | if (GNUNET_OK != register_neighbors (c)) | ||
2478 | { | ||
2479 | if (0 == own_pos) | ||
2480 | { | ||
2481 | path_invalidate (c->path); | ||
2482 | c->t = NULL; | ||
2483 | c->path = NULL; | ||
2484 | } | ||
2485 | GMC_destroy (c); | ||
2486 | return NULL; | ||
2487 | } | ||
2488 | |||
2489 | return c; | ||
2490 | } | ||
2491 | |||
2492 | |||
2493 | void | ||
2494 | GMC_destroy (struct CadetConnection *c) | ||
2495 | { | ||
2496 | if (NULL == c) | ||
2497 | { | ||
2498 | GNUNET_break (0); | ||
2499 | return; | ||
2500 | } | ||
2501 | |||
2502 | if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */ | ||
2503 | return; /* -> message_sent -> GMC_destroy. Don't loop. */ | ||
2504 | c->destroy = 2; | ||
2505 | |||
2506 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c)); | ||
2507 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n", | ||
2508 | &c->fwd_fc, &c->bck_fc); | ||
2509 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", | ||
2510 | c->fwd_fc.poll_task, c->bck_fc.poll_task); | ||
2511 | |||
2512 | /* Cancel all traffic */ | ||
2513 | if (NULL != c->path) | ||
2514 | { | ||
2515 | connection_cancel_queues (c, GNUNET_YES); | ||
2516 | connection_cancel_queues (c, GNUNET_NO); | ||
2517 | unregister_neighbors (c); | ||
2518 | } | ||
2519 | |||
2520 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", | ||
2521 | c->fwd_fc.poll_task, c->bck_fc.poll_task); | ||
2522 | |||
2523 | /* Cancel maintainance task (keepalive/timeout) */ | ||
2524 | if (NULL != c->fwd_fc.poll_msg) | ||
2525 | { | ||
2526 | GMC_cancel (c->fwd_fc.poll_msg); | ||
2527 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n"); | ||
2528 | } | ||
2529 | if (NULL != c->bck_fc.poll_msg) | ||
2530 | { | ||
2531 | GMC_cancel (c->bck_fc.poll_msg); | ||
2532 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n"); | ||
2533 | } | ||
2534 | |||
2535 | /* Delete from tunnel */ | ||
2536 | if (NULL != c->t) | ||
2537 | GMT_remove_connection (c->t, c); | ||
2538 | |||
2539 | if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path) | ||
2540 | path_destroy (c->path); | ||
2541 | if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task) | ||
2542 | GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); | ||
2543 | if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task) | ||
2544 | GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); | ||
2545 | if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task) | ||
2546 | { | ||
2547 | GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task); | ||
2548 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n"); | ||
2549 | } | ||
2550 | if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task) | ||
2551 | { | ||
2552 | GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task); | ||
2553 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n"); | ||
2554 | } | ||
2555 | |||
2556 | GNUNET_break (GNUNET_YES == | ||
2557 | GNUNET_CONTAINER_multihashmap_remove (connections, | ||
2558 | GMC_get_h (c), c)); | ||
2559 | |||
2560 | GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO); | ||
2561 | GNUNET_free (c); | ||
2562 | } | ||
2563 | |||
2564 | /** | ||
2565 | * Get the connection ID. | ||
2566 | * | ||
2567 | * @param c Connection to get the ID from. | ||
2568 | * | ||
2569 | * @return ID of the connection. | ||
2570 | */ | ||
2571 | const struct GNUNET_CADET_Hash * | ||
2572 | GMC_get_id (const struct CadetConnection *c) | ||
2573 | { | ||
2574 | return &c->id; | ||
2575 | } | ||
2576 | |||
2577 | |||
2578 | /** | ||
2579 | * Get the connection ID. | ||
2580 | * | ||
2581 | * @param c Connection to get the ID from. | ||
2582 | * | ||
2583 | * @return ID of the connection. | ||
2584 | */ | ||
2585 | const struct GNUNET_HashCode * | ||
2586 | GMC_get_h (const struct CadetConnection *c) | ||
2587 | { | ||
2588 | return GM_h2hc (&c->id); | ||
2589 | } | ||
2590 | |||
2591 | |||
2592 | /** | ||
2593 | * Get the connection path. | ||
2594 | * | ||
2595 | * @param c Connection to get the path from. | ||
2596 | * | ||
2597 | * @return path used by the connection. | ||
2598 | */ | ||
2599 | const struct CadetPeerPath * | ||
2600 | GMC_get_path (const struct CadetConnection *c) | ||
2601 | { | ||
2602 | if (GNUNET_NO == c->destroy) | ||
2603 | return c->path; | ||
2604 | return NULL; | ||
2605 | } | ||
2606 | |||
2607 | |||
2608 | /** | ||
2609 | * Get the connection state. | ||
2610 | * | ||
2611 | * @param c Connection to get the state from. | ||
2612 | * | ||
2613 | * @return state of the connection. | ||
2614 | */ | ||
2615 | enum CadetConnectionState | ||
2616 | GMC_get_state (const struct CadetConnection *c) | ||
2617 | { | ||
2618 | return c->state; | ||
2619 | } | ||
2620 | |||
2621 | /** | ||
2622 | * Get the connection tunnel. | ||
2623 | * | ||
2624 | * @param c Connection to get the tunnel from. | ||
2625 | * | ||
2626 | * @return tunnel of the connection. | ||
2627 | */ | ||
2628 | struct CadetTunnel3 * | ||
2629 | GMC_get_tunnel (const struct CadetConnection *c) | ||
2630 | { | ||
2631 | return c->t; | ||
2632 | } | ||
2633 | |||
2634 | |||
2635 | /** | ||
2636 | * Get free buffer space in a connection. | ||
2637 | * | ||
2638 | * @param c Connection. | ||
2639 | * @param fwd Is query about FWD traffic? | ||
2640 | * | ||
2641 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
2642 | */ | ||
2643 | unsigned int | ||
2644 | GMC_get_buffer (struct CadetConnection *c, int fwd) | ||
2645 | { | ||
2646 | struct CadetFlowControl *fc; | ||
2647 | |||
2648 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2649 | |||
2650 | return (fc->queue_max - fc->queue_n); | ||
2651 | } | ||
2652 | |||
2653 | /** | ||
2654 | * Get how many messages have we allowed to send to us from a direction. | ||
2655 | * | ||
2656 | * @param c Connection. | ||
2657 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | ||
2658 | * | ||
2659 | * @return last_ack_sent - last_pid_recv | ||
2660 | */ | ||
2661 | unsigned int | ||
2662 | GMC_get_allowed (struct CadetConnection *c, int fwd) | ||
2663 | { | ||
2664 | struct CadetFlowControl *fc; | ||
2665 | |||
2666 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2667 | if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent)) | ||
2668 | { | ||
2669 | return 0; | ||
2670 | } | ||
2671 | return (fc->last_ack_sent - fc->last_pid_recv); | ||
2672 | } | ||
2673 | |||
2674 | /** | ||
2675 | * Get messages queued in a connection. | ||
2676 | * | ||
2677 | * @param c Connection. | ||
2678 | * @param fwd Is query about FWD traffic? | ||
2679 | * | ||
2680 | * @return Number of messages queued. | ||
2681 | */ | ||
2682 | unsigned int | ||
2683 | GMC_get_qn (struct CadetConnection *c, int fwd) | ||
2684 | { | ||
2685 | struct CadetFlowControl *fc; | ||
2686 | |||
2687 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2688 | |||
2689 | return fc->queue_n; | ||
2690 | } | ||
2691 | |||
2692 | |||
2693 | /** | ||
2694 | * Get next PID to use. | ||
2695 | * | ||
2696 | * @param c Connection. | ||
2697 | * @param fwd Is query about FWD traffic? | ||
2698 | * | ||
2699 | * @return Last PID used + 1. | ||
2700 | */ | ||
2701 | unsigned int | ||
2702 | GMC_get_pid (struct CadetConnection *c, int fwd) | ||
2703 | { | ||
2704 | struct CadetFlowControl *fc; | ||
2705 | |||
2706 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2707 | |||
2708 | return fc->last_pid_sent + 1; | ||
2709 | } | ||
2710 | |||
2711 | |||
2712 | /** | ||
2713 | * Allow the connection to advertise a buffer of the given size. | ||
2714 | * | ||
2715 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
2716 | * allowing up to last_pid_recv + buffer. | ||
2717 | * | ||
2718 | * @param c Connection. | ||
2719 | * @param buffer How many more messages the connection can accept. | ||
2720 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
2721 | */ | ||
2722 | void | ||
2723 | GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd) | ||
2724 | { | ||
2725 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n", | ||
2726 | GMC_2s (c), buffer, GM_f2s (fwd)); | ||
2727 | send_ack (c, buffer, fwd, GNUNET_NO); | ||
2728 | } | ||
2729 | |||
2730 | |||
2731 | /** | ||
2732 | * Notify other peers on a connection of a broken link. Mark connections | ||
2733 | * to destroy after all traffic has been sent. | ||
2734 | * | ||
2735 | * @param c Connection on which there has been a disconnection. | ||
2736 | * @param peer Peer that disconnected. | ||
2737 | */ | ||
2738 | void | ||
2739 | GMC_notify_broken (struct CadetConnection *c, | ||
2740 | struct CadetPeer *peer) | ||
2741 | { | ||
2742 | int fwd; | ||
2743 | |||
2744 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2745 | " notify broken on %s due to %s disconnect\n", | ||
2746 | GMC_2s (c), GMP_2s (peer)); | ||
2747 | |||
2748 | fwd = peer == get_prev_hop (c); | ||
2749 | |||
2750 | if (GNUNET_YES == GMC_is_terminal (c, fwd)) | ||
2751 | { | ||
2752 | /* Local shutdown, no one to notify about this. */ | ||
2753 | GMC_destroy (c); | ||
2754 | return; | ||
2755 | } | ||
2756 | if (GNUNET_NO == c->destroy) | ||
2757 | send_broken (c, &my_full_id, GMP_get_id (peer), fwd); | ||
2758 | |||
2759 | /* Connection will have at least one pending message | ||
2760 | * (the one we just scheduled), so no point in checking whether to | ||
2761 | * destroy immediately. */ | ||
2762 | c->destroy = GNUNET_YES; | ||
2763 | c->state = CADET_CONNECTION_DESTROYED; | ||
2764 | |||
2765 | /** | ||
2766 | * Cancel all queues, if no message is left, connection will be destroyed. | ||
2767 | */ | ||
2768 | connection_cancel_queues (c, !fwd); | ||
2769 | |||
2770 | return; | ||
2771 | } | ||
2772 | |||
2773 | |||
2774 | /** | ||
2775 | * Is this peer the first one on the connection? | ||
2776 | * | ||
2777 | * @param c Connection. | ||
2778 | * @param fwd Is this about fwd traffic? | ||
2779 | * | ||
2780 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
2781 | */ | ||
2782 | int | ||
2783 | GMC_is_origin (struct CadetConnection *c, int fwd) | ||
2784 | { | ||
2785 | if (!fwd && c->path->length - 1 == c->own_pos ) | ||
2786 | return GNUNET_YES; | ||
2787 | if (fwd && 0 == c->own_pos) | ||
2788 | return GNUNET_YES; | ||
2789 | return GNUNET_NO; | ||
2790 | } | ||
2791 | |||
2792 | |||
2793 | /** | ||
2794 | * Is this peer the last one on the connection? | ||
2795 | * | ||
2796 | * @param c Connection. | ||
2797 | * @param fwd Is this about fwd traffic? | ||
2798 | * Note that the ROOT is the terminal for BCK traffic! | ||
2799 | * | ||
2800 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | ||
2801 | */ | ||
2802 | int | ||
2803 | GMC_is_terminal (struct CadetConnection *c, int fwd) | ||
2804 | { | ||
2805 | return GMC_is_origin (c, !fwd); | ||
2806 | } | ||
2807 | |||
2808 | |||
2809 | /** | ||
2810 | * See if we are allowed to send by the next hop in the given direction. | ||
2811 | * | ||
2812 | * @param c Connection. | ||
2813 | * @param fwd Is this about fwd traffic? | ||
2814 | * | ||
2815 | * @return #GNUNET_YES in case it's OK to send. | ||
2816 | */ | ||
2817 | int | ||
2818 | GMC_is_sendable (struct CadetConnection *c, int fwd) | ||
2819 | { | ||
2820 | struct CadetFlowControl *fc; | ||
2821 | |||
2822 | LOG (GNUNET_ERROR_TYPE_DEBUG, " checking sendability of %s traffic on %s\n", | ||
2823 | GM_f2s (fwd), GMC_2s (c)); | ||
2824 | if (NULL == c) | ||
2825 | { | ||
2826 | GNUNET_break (0); | ||
2827 | return GNUNET_YES; | ||
2828 | } | ||
2829 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2830 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2831 | " last ack recv: %u, last pid sent: %u\n", | ||
2832 | fc->last_ack_recv, fc->last_pid_sent); | ||
2833 | if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) | ||
2834 | { | ||
2835 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n"); | ||
2836 | return GNUNET_YES; | ||
2837 | } | ||
2838 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
2839 | return GNUNET_NO; | ||
2840 | } | ||
2841 | |||
2842 | |||
2843 | /** | ||
2844 | * Check if this connection is a direct one (never trim a direct connection). | ||
2845 | * | ||
2846 | * @param c Connection. | ||
2847 | * | ||
2848 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
2849 | */ | ||
2850 | int | ||
2851 | GMC_is_direct (struct CadetConnection *c) | ||
2852 | { | ||
2853 | return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO; | ||
2854 | } | ||
2855 | |||
2856 | /** | ||
2857 | * Sends an already built message on a connection, properly registering | ||
2858 | * all used resources. | ||
2859 | * | ||
2860 | * @param message Message to send. Function makes a copy of it. | ||
2861 | * If message is not hop-by-hop, decrements TTL of copy. | ||
2862 | * @param payload_type Type of payload, in case the message is encrypted. | ||
2863 | * @param c Connection on which this message is transmitted. | ||
2864 | * @param fwd Is this a fwd message? | ||
2865 | * @param force Force the connection to accept the message (buffer overfill). | ||
2866 | * @param cont Continuation called once message is sent. Can be NULL. | ||
2867 | * @param cont_cls Closure for @c cont. | ||
2868 | * | ||
2869 | * @return Handle to cancel the message before it's sent. | ||
2870 | * NULL on error or if @c cont is NULL. | ||
2871 | * Invalid on @c cont call. | ||
2872 | */ | ||
2873 | struct CadetConnectionQueue * | ||
2874 | GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2875 | uint16_t payload_type, uint32_t payload_id, | ||
2876 | struct CadetConnection *c, int fwd, int force, | ||
2877 | GMC_sent cont, void *cont_cls) | ||
2878 | { | ||
2879 | struct CadetFlowControl *fc; | ||
2880 | struct CadetConnectionQueue *q; | ||
2881 | void *data; | ||
2882 | size_t size; | ||
2883 | uint16_t type; | ||
2884 | int droppable; | ||
2885 | |||
2886 | size = ntohs (message->size); | ||
2887 | data = GNUNET_malloc (size); | ||
2888 | memcpy (data, message, size); | ||
2889 | type = ntohs (message->type); | ||
2890 | LOG (GNUNET_ERROR_TYPE_INFO, "--> %s (%s %u) on connection %s (%u bytes)\n", | ||
2891 | GM_m2s (type), GM_m2s (payload_type), payload_id, GMC_2s (c), size); | ||
2892 | |||
2893 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2894 | droppable = GNUNET_NO == force; | ||
2895 | switch (type) | ||
2896 | { | ||
2897 | struct GNUNET_CADET_Encrypted *emsg; | ||
2898 | struct GNUNET_CADET_KX *kmsg; | ||
2899 | struct GNUNET_CADET_ACK *amsg; | ||
2900 | struct GNUNET_CADET_Poll *pmsg; | ||
2901 | struct GNUNET_CADET_ConnectionDestroy *dmsg; | ||
2902 | struct GNUNET_CADET_ConnectionBroken *bmsg; | ||
2903 | uint32_t ttl; | ||
2904 | |||
2905 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
2906 | emsg = (struct GNUNET_CADET_Encrypted *) data; | ||
2907 | ttl = ntohl (emsg->ttl); | ||
2908 | if (0 == ttl) | ||
2909 | { | ||
2910 | GNUNET_break_op (0); | ||
2911 | GNUNET_free (data); | ||
2912 | return NULL; | ||
2913 | } | ||
2914 | emsg->cid = c->id; | ||
2915 | emsg->ttl = htonl (ttl - 1); | ||
2916 | emsg->pid = htonl (0); | ||
2917 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n); | ||
2918 | LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent); | ||
2919 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ack recv %u\n", fc->last_ack_recv); | ||
2920 | if (GNUNET_YES == droppable) | ||
2921 | { | ||
2922 | fc->queue_n++; | ||
2923 | } | ||
2924 | else | ||
2925 | { | ||
2926 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not droppable, Q_N stays the same\n"); | ||
2927 | } | ||
2928 | if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv)) | ||
2929 | { | ||
2930 | GMC_start_poll (c, fwd); | ||
2931 | } | ||
2932 | break; | ||
2933 | |||
2934 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
2935 | kmsg = (struct GNUNET_CADET_KX *) data; | ||
2936 | kmsg->cid = c->id; | ||
2937 | break; | ||
2938 | |||
2939 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
2940 | amsg = (struct GNUNET_CADET_ACK *) data; | ||
2941 | amsg->cid = c->id; | ||
2942 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack)); | ||
2943 | droppable = GNUNET_NO; | ||
2944 | break; | ||
2945 | |||
2946 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
2947 | pmsg = (struct GNUNET_CADET_Poll *) data; | ||
2948 | pmsg->cid = c->id; | ||
2949 | LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid)); | ||
2950 | droppable = GNUNET_NO; | ||
2951 | break; | ||
2952 | |||
2953 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
2954 | dmsg = (struct GNUNET_CADET_ConnectionDestroy *) data; | ||
2955 | dmsg->cid = c->id; | ||
2956 | break; | ||
2957 | |||
2958 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
2959 | bmsg = (struct GNUNET_CADET_ConnectionBroken *) data; | ||
2960 | bmsg->cid = c->id; | ||
2961 | break; | ||
2962 | |||
2963 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
2964 | GNUNET_break (0); | ||
2965 | /* falltrough */ | ||
2966 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
2967 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
2968 | break; | ||
2969 | |||
2970 | default: | ||
2971 | GNUNET_break (0); | ||
2972 | GNUNET_free (data); | ||
2973 | return NULL; | ||
2974 | } | ||
2975 | |||
2976 | if (fc->queue_n > fc->queue_max && droppable) | ||
2977 | { | ||
2978 | GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", | ||
2979 | 1, GNUNET_NO); | ||
2980 | GNUNET_break (0); | ||
2981 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2982 | "queue full: %u/%u\n", | ||
2983 | fc->queue_n, fc->queue_max); | ||
2984 | if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type) | ||
2985 | { | ||
2986 | fc->queue_n--; | ||
2987 | } | ||
2988 | GNUNET_free (data); | ||
2989 | return NULL; /* Drop this message */ | ||
2990 | } | ||
2991 | |||
2992 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u\n", c, c->pending_messages); | ||
2993 | // c->pending_messages++; | ||
2994 | |||
2995 | q = GNUNET_new (struct CadetConnectionQueue); | ||
2996 | q->forced = !droppable; | ||
2997 | q->q = GMP_queue_add (get_hop (c, fwd), data, type, payload_type, payload_id, | ||
2998 | size, c, fwd, &conn_message_sent, q); | ||
2999 | if (NULL == q->q) | ||
3000 | { | ||
3001 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING dropping msg on %s\n", GMC_2s (c)); | ||
3002 | GNUNET_free (data); | ||
3003 | GNUNET_free (q); | ||
3004 | return NULL; | ||
3005 | } | ||
3006 | q->cont = cont; | ||
3007 | q->cont_cls = cont_cls; | ||
3008 | return (NULL == cont) ? NULL : q; | ||
3009 | } | ||
3010 | |||
3011 | |||
3012 | /** | ||
3013 | * Cancel a previously sent message while it's in the queue. | ||
3014 | * | ||
3015 | * ONLY can be called before the continuation given to the send function | ||
3016 | * is called. Once the continuation is called, the message is no longer in the | ||
3017 | * queue. | ||
3018 | * | ||
3019 | * @param q Handle to the queue. | ||
3020 | */ | ||
3021 | void | ||
3022 | GMC_cancel (struct CadetConnectionQueue *q) | ||
3023 | { | ||
3024 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! GMC cancel message\n"); | ||
3025 | |||
3026 | /* queue destroy calls message_sent, which calls q->cont and frees q */ | ||
3027 | GMP_queue_destroy (q->q, GNUNET_YES, GNUNET_NO, 0); | ||
3028 | } | ||
3029 | |||
3030 | |||
3031 | /** | ||
3032 | * Sends a CREATE CONNECTION message for a path to a peer. | ||
3033 | * Changes the connection and tunnel states if necessary. | ||
3034 | * | ||
3035 | * @param connection Connection to create. | ||
3036 | */ | ||
3037 | void | ||
3038 | GMC_send_create (struct CadetConnection *connection) | ||
3039 | { | ||
3040 | enum CadetTunnel3CState state; | ||
3041 | size_t size; | ||
3042 | |||
3043 | size = sizeof (struct GNUNET_CADET_ConnectionCreate); | ||
3044 | size += connection->path->length * sizeof (struct GNUNET_PeerIdentity); | ||
3045 | |||
3046 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s on connection %s (%u bytes)\n", | ||
3047 | GM_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), | ||
3048 | GMC_2s (connection), size); | ||
3049 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", | ||
3050 | connection, connection->pending_messages); | ||
3051 | connection->pending_messages++; | ||
3052 | |||
3053 | connection->maintenance_q = | ||
3054 | GMP_queue_add (get_next_hop (connection), NULL, | ||
3055 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
3056 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0, | ||
3057 | size, connection, GNUNET_YES, &conn_message_sent, NULL); | ||
3058 | |||
3059 | state = GMT_get_cstate (connection->t); | ||
3060 | if (CADET_TUNNEL3_SEARCHING == state || CADET_TUNNEL3_NEW == state) | ||
3061 | GMT_change_cstate (connection->t, CADET_TUNNEL3_WAITING); | ||
3062 | if (CADET_CONNECTION_NEW == connection->state) | ||
3063 | connection_change_state (connection, CADET_CONNECTION_SENT); | ||
3064 | } | ||
3065 | |||
3066 | |||
3067 | /** | ||
3068 | * Send a message to all peers in this connection that the connection | ||
3069 | * is no longer valid. | ||
3070 | * | ||
3071 | * If some peer should not receive the message, it should be zero'ed out | ||
3072 | * before calling this function. | ||
3073 | * | ||
3074 | * @param c The connection whose peers to notify. | ||
3075 | */ | ||
3076 | void | ||
3077 | GMC_send_destroy (struct CadetConnection *c) | ||
3078 | { | ||
3079 | struct GNUNET_CADET_ConnectionDestroy msg; | ||
3080 | |||
3081 | if (GNUNET_YES == c->destroy) | ||
3082 | return; | ||
3083 | |||
3084 | msg.header.size = htons (sizeof (msg)); | ||
3085 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);; | ||
3086 | msg.cid = c->id; | ||
3087 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3088 | " sending connection destroy for connection %s\n", | ||
3089 | GMC_2s (c)); | ||
3090 | |||
3091 | if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES)) | ||
3092 | GMC_send_prebuilt_message (&msg.header, | ||
3093 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
3094 | c, GNUNET_YES, GNUNET_YES, NULL, NULL); | ||
3095 | if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO)) | ||
3096 | GMC_send_prebuilt_message (&msg.header, | ||
3097 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
3098 | c, GNUNET_NO, GNUNET_YES, NULL, NULL); | ||
3099 | c->destroy = GNUNET_YES; | ||
3100 | c->state = CADET_CONNECTION_DESTROYED; | ||
3101 | } | ||
3102 | |||
3103 | |||
3104 | /** | ||
3105 | * @brief Start a polling timer for the connection. | ||
3106 | * | ||
3107 | * When a neighbor does not accept more traffic on the connection it could be | ||
3108 | * caused by a simple congestion or by a lost ACK. Polling enables to check | ||
3109 | * for the lastest ACK status for a connection. | ||
3110 | * | ||
3111 | * @param c Connection. | ||
3112 | * @param fwd Should we poll in the FWD direction? | ||
3113 | */ | ||
3114 | void | ||
3115 | GMC_start_poll (struct CadetConnection *c, int fwd) | ||
3116 | { | ||
3117 | struct CadetFlowControl *fc; | ||
3118 | |||
3119 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3120 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n", | ||
3121 | GM_f2s (fwd)); | ||
3122 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg) | ||
3123 | { | ||
3124 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** not needed (%u, %p)\n", | ||
3125 | fc->poll_task, fc->poll_msg); | ||
3126 | return; | ||
3127 | } | ||
3128 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n"); | ||
3129 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
3130 | &connection_poll, | ||
3131 | fc); | ||
3132 | } | ||
3133 | |||
3134 | |||
3135 | /** | ||
3136 | * @brief Stop polling a connection for ACKs. | ||
3137 | * | ||
3138 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | ||
3139 | * | ||
3140 | * @param c Connection. | ||
3141 | * @param fwd Should we stop the poll in the FWD direction? | ||
3142 | */ | ||
3143 | void | ||
3144 | GMC_stop_poll (struct CadetConnection *c, int fwd) | ||
3145 | { | ||
3146 | struct CadetFlowControl *fc; | ||
3147 | |||
3148 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3149 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) | ||
3150 | { | ||
3151 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
3152 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
3153 | } | ||
3154 | } | ||
3155 | |||
3156 | /** | ||
3157 | * Get a (static) string for a connection. | ||
3158 | * | ||
3159 | * @param c Connection. | ||
3160 | */ | ||
3161 | const char * | ||
3162 | GMC_2s (const struct CadetConnection *c) | ||
3163 | { | ||
3164 | if (NULL == c) | ||
3165 | return "NULL"; | ||
3166 | |||
3167 | if (NULL != c->t) | ||
3168 | { | ||
3169 | static char buf[128]; | ||
3170 | |||
3171 | sprintf (buf, "%s (->%s)", | ||
3172 | GNUNET_h2s (GM_h2hc (GMC_get_id (c))), GMT_2s (c->t)); | ||
3173 | return buf; | ||
3174 | } | ||
3175 | return GNUNET_h2s (GM_h2hc (&c->id)); | ||
3176 | } | ||