diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_connection.c | 4010 |
1 files changed, 694 insertions, 3316 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index af27647b3..7b66f61a2 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2001-2015 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -17,242 +17,126 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | |||
20 | /** | 21 | /** |
21 | * @file cadet/gnunet-service-cadet_connection.c | 22 | * @file cadet/gnunet-service-cadet_connection.c |
22 | * @brief GNUnet CADET service connection handling | 23 | * @brief management of CORE-level end-to-end connections; establishes |
24 | * end-to-end routes and transmits messages along the route | ||
23 | * @author Bartlomiej Polot | 25 | * @author Bartlomiej Polot |
26 | * @author Christian Grothoff | ||
24 | */ | 27 | */ |
25 | #include "platform.h" | 28 | #include "platform.h" |
26 | #include "gnunet_util_lib.h" | 29 | #include "gnunet-service-cadet_connection.h" |
30 | #include "gnunet-service-cadet_channel.h" | ||
31 | #include "gnunet-service-cadet_paths.h" | ||
32 | #include "gnunet-service-cadet_tunnels.h" | ||
33 | #include "gnunet_cadet_service.h" | ||
27 | #include "gnunet_statistics_service.h" | 34 | #include "gnunet_statistics_service.h" |
28 | #include "cadet_path.h" | ||
29 | #include "cadet_protocol.h" | 35 | #include "cadet_protocol.h" |
30 | #include "cadet.h" | ||
31 | #include "gnunet-service-cadet_connection.h" | ||
32 | #include "gnunet-service-cadet_peer.h" | ||
33 | #include "gnunet-service-cadet_tunnel.h" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Should we run somewhat expensive checks on our invariants? | ||
38 | */ | ||
39 | #define CHECK_INVARIANTS 0 | ||
40 | |||
41 | |||
42 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__) | ||
43 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
44 | |||
45 | |||
46 | #define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ | ||
47 | GNUNET_TIME_UNIT_MINUTES,\ | ||
48 | 10) | ||
49 | #define AVG_MSGS 32 | ||
50 | |||
51 | |||
52 | /******************************************************************************/ | ||
53 | /******************************** STRUCTS **********************************/ | ||
54 | /******************************************************************************/ | ||
55 | |||
56 | /** | ||
57 | * Handle for messages queued but not yet sent. | ||
58 | */ | ||
59 | struct CadetConnectionQueue | ||
60 | { | ||
61 | 36 | ||
62 | struct CadetConnectionQueue *next; | ||
63 | struct CadetConnectionQueue *prev; | ||
64 | 37 | ||
65 | /** | 38 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__) |
66 | * Peer queue handle, to cancel if necessary. | ||
67 | */ | ||
68 | struct CadetPeerQueue *peer_q; | ||
69 | |||
70 | /** | ||
71 | * Continuation to call once sent. | ||
72 | */ | ||
73 | GCC_sent cont; | ||
74 | |||
75 | /** | ||
76 | * Closure for @e cont. | ||
77 | */ | ||
78 | void *cont_cls; | ||
79 | |||
80 | /** | ||
81 | * Was this a forced message? (Do not account for it) | ||
82 | */ | ||
83 | int forced; | ||
84 | }; | ||
85 | 39 | ||
86 | 40 | ||
87 | /** | 41 | /** |
88 | * Struct to encapsulate all the Flow Control information to a peer to which | 42 | * All the states a connection can be in. |
89 | * we are directly connected (on a core level). | ||
90 | */ | 43 | */ |
91 | struct CadetFlowControl | 44 | enum CadetConnectionState |
92 | { | 45 | { |
93 | /** | 46 | /** |
94 | * Connection this controls. | 47 | * Uninitialized status, we have not yet even gotten the message queue. |
95 | */ | ||
96 | struct CadetConnection *c; | ||
97 | |||
98 | struct CadetConnectionQueue *q_head; | ||
99 | struct CadetConnectionQueue *q_tail; | ||
100 | |||
101 | /** | ||
102 | * How many messages are in the queue on this connection. | ||
103 | */ | ||
104 | unsigned int queue_n; | ||
105 | |||
106 | /** | ||
107 | * How many messages do we accept in the queue. | ||
108 | * If 0, the connection is broken in this direction (next hop disconnected). | ||
109 | */ | ||
110 | unsigned int queue_max; | ||
111 | |||
112 | /** | ||
113 | * ID of the next packet to send. | ||
114 | */ | ||
115 | struct CadetEncryptedMessageIdentifier next_pid; | ||
116 | |||
117 | /** | ||
118 | * ID of the last packet sent towards the peer. | ||
119 | */ | ||
120 | struct CadetEncryptedMessageIdentifier last_pid_sent; | ||
121 | |||
122 | /** | ||
123 | * ID of the last packet received from the peer. | ||
124 | */ | ||
125 | struct CadetEncryptedMessageIdentifier last_pid_recv; | ||
126 | |||
127 | /** | ||
128 | * Bitmap of past 32 messages received: | ||
129 | * - LSB being @c last_pid_recv. | ||
130 | * - MSB being @c last_pid_recv - 31 (mod UINTMAX). | ||
131 | */ | ||
132 | uint32_t recv_bitmap; | ||
133 | |||
134 | /** | ||
135 | * Last ACK sent to the peer (peer is not allowed to send | ||
136 | * messages with PIDs higher than this value). | ||
137 | */ | 48 | */ |
138 | struct CadetEncryptedMessageIdentifier last_ack_sent; | 49 | CADET_CONNECTION_NEW, |
139 | 50 | ||
140 | /** | 51 | /** |
141 | * Last ACK sent towards the origin (for traffic towards leaf node). | 52 | * Connection create message in queue, awaiting transmission by CORE. |
142 | */ | 53 | */ |
143 | struct CadetEncryptedMessageIdentifier last_ack_recv; | 54 | CADET_CONNECTION_SENDING_CREATE, |
144 | 55 | ||
145 | /** | 56 | /** |
146 | * Task to poll the peer in case of a lost ACK causes stall. | 57 | * Connection create message sent, waiting for ACK. |
147 | */ | 58 | */ |
148 | struct GNUNET_SCHEDULER_Task *poll_task; | 59 | CADET_CONNECTION_SENT, |
149 | 60 | ||
150 | /** | 61 | /** |
151 | * How frequently to poll for ACKs. | 62 | * We are an inbound connection, and received a CREATE. Need to |
63 | * send an CREATE_ACK back. | ||
152 | */ | 64 | */ |
153 | struct GNUNET_TIME_Relative poll_time; | 65 | CADET_CONNECTION_CREATE_RECEIVED, |
154 | 66 | ||
155 | /** | 67 | /** |
156 | * Queued poll message, to cancel if not necessary anymore (got ACK). | 68 | * Connection confirmed, ready to carry traffic. |
157 | */ | 69 | */ |
158 | struct CadetConnectionQueue *poll_msg; | 70 | CADET_CONNECTION_READY |
159 | 71 | ||
160 | /** | ||
161 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
162 | */ | ||
163 | struct CadetConnectionQueue *ack_msg; | ||
164 | }; | 72 | }; |
165 | 73 | ||
74 | |||
166 | /** | 75 | /** |
167 | * Keep a record of the last messages sent on this connection. | 76 | * Low-level connection to a destination. |
168 | */ | 77 | */ |
169 | struct CadetConnectionPerformance | 78 | struct CadetConnection |
170 | { | 79 | { |
171 | /** | ||
172 | * Circular buffer for storing measurements. | ||
173 | */ | ||
174 | double usecsperbyte[AVG_MSGS]; | ||
175 | 80 | ||
176 | /** | 81 | /** |
177 | * Running average of @c usecsperbyte. | 82 | * ID of the connection. |
178 | */ | ||
179 | double avg; | ||
180 | |||
181 | /** | ||
182 | * How many values of @c usecsperbyte are valid. | ||
183 | */ | ||
184 | uint16_t size; | ||
185 | |||
186 | /** | ||
187 | * Index of the next "free" position in @c usecsperbyte. | ||
188 | */ | 83 | */ |
189 | uint16_t idx; | 84 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
190 | }; | ||
191 | |||
192 | 85 | ||
193 | /** | ||
194 | * Struct containing all information regarding a connection to a peer. | ||
195 | */ | ||
196 | struct CadetConnection | ||
197 | { | ||
198 | /** | 86 | /** |
199 | * Tunnel this connection is part of. | 87 | * To which peer does this connection go? |
200 | */ | 88 | */ |
201 | struct CadetTunnel *t; | 89 | struct CadetPeer *destination; |
202 | 90 | ||
203 | /** | 91 | /** |
204 | * Flow control information for traffic fwd. | 92 | * Which tunnel is using this connection? |
205 | */ | 93 | */ |
206 | struct CadetFlowControl fwd_fc; | 94 | struct CadetTConnection *ct; |
207 | 95 | ||
208 | /** | 96 | /** |
209 | * Flow control information for traffic bck. | 97 | * Path we are using to our destination. |
210 | */ | 98 | */ |
211 | struct CadetFlowControl bck_fc; | 99 | struct CadetPeerPath *path; |
212 | 100 | ||
213 | /** | 101 | /** |
214 | * Measure connection performance on the endpoint. | 102 | * Pending message, NULL if we are ready to transmit. |
215 | */ | 103 | */ |
216 | struct CadetConnectionPerformance *perf; | 104 | struct GNUNET_MQ_Envelope *env; |
217 | 105 | ||
218 | /** | 106 | /** |
219 | * ID of the connection. | 107 | * Handle for calling #GCP_request_mq_cancel() once we are finished. |
220 | */ | 108 | */ |
221 | struct GNUNET_CADET_ConnectionTunnelIdentifier id; | 109 | struct GCP_MessageQueueManager *mq_man; |
222 | 110 | ||
223 | /** | 111 | /** |
224 | * Path being used for the tunnel. At the origin of the connection | 112 | * Task for connection maintenance. |
225 | * it's a pointer to the destination's path pool, otherwise just a copy. | ||
226 | */ | 113 | */ |
227 | struct CadetPeerPath *path; | 114 | struct GNUNET_SCHEDULER_Task *task; |
228 | 115 | ||
229 | /** | 116 | /** |
230 | * Task to keep the used paths alive at the owner, | 117 | * Queue entry for keepalive messages. |
231 | * time tunnel out on all the other peers. | ||
232 | */ | 118 | */ |
233 | struct GNUNET_SCHEDULER_Task *fwd_maintenance_task; | 119 | struct CadetTunnelQueueEntry *keepalive_qe; |
234 | 120 | ||
235 | /** | 121 | /** |
236 | * Task to keep the used paths alive at the destination, | 122 | * Function to call once we are ready to transmit. |
237 | * time tunnel out on all the other peers. | ||
238 | */ | 123 | */ |
239 | struct GNUNET_SCHEDULER_Task *bck_maintenance_task; | 124 | GCC_ReadyCallback ready_cb; |
240 | 125 | ||
241 | /** | 126 | /** |
242 | * Queue handle for maintainance traffic. One handle for FWD and BCK since | 127 | * Closure for @e ready_cb. |
243 | * one peer never needs to maintain both directions (no loopback connections). | ||
244 | */ | 128 | */ |
245 | struct CadetPeerQueue *maintenance_q; | 129 | void *ready_cb_cls; |
246 | 130 | ||
247 | /** | 131 | /** |
248 | * Should equal #get_next_hop(), or NULL if that peer disconnected. | 132 | * How long do we wait before we try again with a CREATE message? |
249 | */ | 133 | */ |
250 | struct CadetPeer *next_peer; | 134 | struct GNUNET_TIME_Relative retry_delay; |
251 | 135 | ||
252 | /** | 136 | /** |
253 | * Should equal #get_prev_hop(), or NULL if that peer disconnected. | 137 | * Performance metrics for this connection. |
254 | */ | 138 | */ |
255 | struct CadetPeer *prev_peer; | 139 | struct CadetConnectionMetrics metrics; |
256 | 140 | ||
257 | /** | 141 | /** |
258 | * State of the connection. | 142 | * State of the connection. |
@@ -260,221 +144,36 @@ struct CadetConnection | |||
260 | enum CadetConnectionState state; | 144 | enum CadetConnectionState state; |
261 | 145 | ||
262 | /** | 146 | /** |
263 | * Position of the local peer in the path. | 147 | * Options for the route, control buffering. |
264 | */ | 148 | */ |
265 | unsigned int own_pos; | 149 | enum GNUNET_CADET_ChannelOption options; |
266 | 150 | ||
267 | /** | 151 | /** |
268 | * Pending message count. | 152 | * How many latency observations did we make for this connection? |
269 | */ | 153 | */ |
270 | unsigned int pending_messages; | 154 | unsigned int latency_datapoints; |
271 | 155 | ||
272 | /** | 156 | /** |
273 | * Destroy flag: | 157 | * Offset of our @e destination in @e path. |
274 | * - if 0, connection in use. | ||
275 | * - if 1, destroy on last message. | ||
276 | * - if 2, connection is being destroyed don't re-enter. | ||
277 | */ | 158 | */ |
278 | int destroy; | 159 | unsigned int off; |
279 | 160 | ||
280 | /** | 161 | /** |
281 | * In-connection-map flag. Sometimes, when @e destroy is set but | 162 | * Are we ready to transmit via @e mq_man right now? |
282 | * actual destruction is delayed to enable us to finish processing | ||
283 | * queues (i.e. in the direction that is still working), we remove | ||
284 | * the connection from the map to prevent it from still being | ||
285 | * found (and used) by accident. This flag is set to #GNUNET_YES | ||
286 | * for a connection that is not in the #connections map. Should | ||
287 | * only be #GNUNET_YES if #destroy is also non-zero. | ||
288 | */ | 163 | */ |
289 | int was_removed; | 164 | int mqm_ready; |
290 | 165 | ||
291 | /** | ||
292 | * Counter to do exponential backoff when creating a connection (max 64). | ||
293 | */ | ||
294 | unsigned short create_retry; | ||
295 | |||
296 | /** | ||
297 | * Task to check if connection has duplicates. | ||
298 | */ | ||
299 | struct GNUNET_SCHEDULER_Task *check_duplicates_task; | ||
300 | }; | 166 | }; |
301 | 167 | ||
302 | 168 | ||
303 | /******************************************************************************/ | ||
304 | /******************************* GLOBALS ***********************************/ | ||
305 | /******************************************************************************/ | ||
306 | |||
307 | /** | ||
308 | * Global handle to the statistics service. | ||
309 | */ | ||
310 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
311 | |||
312 | /** | ||
313 | * Local peer own ID (memory efficient handle). | ||
314 | */ | ||
315 | extern GNUNET_PEER_Id myid; | ||
316 | |||
317 | /** | ||
318 | * Local peer own ID (full value). | ||
319 | */ | ||
320 | extern struct GNUNET_PeerIdentity my_full_id; | ||
321 | |||
322 | /** | ||
323 | * Connections known, indexed by cid (CadetConnection). | ||
324 | */ | ||
325 | static struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
326 | |||
327 | /** | ||
328 | * How many connections are we willing to maintain. | ||
329 | * Local connections are always allowed, | ||
330 | * even if there are more connections than max. | ||
331 | */ | ||
332 | static unsigned long long max_connections; | ||
333 | |||
334 | /** | ||
335 | * How many messages *in total* are we willing to queue, divide by number of | ||
336 | * connections to get connection queue size. | ||
337 | */ | ||
338 | static unsigned long long max_msgs_queue; | ||
339 | |||
340 | /** | ||
341 | * How often to send path keepalives. Paths timeout after 4 missed. | ||
342 | */ | ||
343 | static struct GNUNET_TIME_Relative refresh_connection_time; | ||
344 | |||
345 | /** | ||
346 | * How often to send path create / ACKs. | ||
347 | */ | ||
348 | static struct GNUNET_TIME_Relative create_connection_time; | ||
349 | |||
350 | |||
351 | /******************************************************************************/ | ||
352 | /******************************** STATIC ***********************************/ | ||
353 | /******************************************************************************/ | ||
354 | |||
355 | |||
356 | |||
357 | #if 0 // avoid compiler warning for unused static function | ||
358 | static void | ||
359 | fc_debug (struct CadetFlowControl *fc) | ||
360 | { | ||
361 | LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", | ||
362 | ntohl (fc->last_pid_recv.pid), | ||
363 | ntohl (fc->last_ack_sent.pid)); | ||
364 | LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", | ||
365 | fc->last_pid_sent, fc->last_ack_recv); | ||
366 | LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", | ||
367 | fc->queue_n, fc->queue_max); | ||
368 | } | ||
369 | |||
370 | static void | ||
371 | connection_debug (struct CadetConnection *c) | ||
372 | { | ||
373 | if (NULL == c) | ||
374 | { | ||
375 | LOG (GNUNET_ERROR_TYPE_INFO, "DEBUG NULL CONNECTION\n"); | ||
376 | return; | ||
377 | } | ||
378 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", | ||
379 | peer2s (c->t->peer), GCC_2s (c)); | ||
380 | LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", | ||
381 | c->state, c->pending_messages); | ||
382 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
383 | fc_debug (&c->fwd_fc); | ||
384 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
385 | fc_debug (&c->bck_fc); | ||
386 | } | ||
387 | #endif | ||
388 | |||
389 | |||
390 | /** | ||
391 | * Schedule next keepalive task, taking in consideration | ||
392 | * the connection state and number of retries. | ||
393 | * | ||
394 | * @param c Connection for which to schedule the next keepalive. | ||
395 | * @param fwd Direction for the next keepalive. | ||
396 | */ | ||
397 | static void | ||
398 | schedule_next_keepalive (struct CadetConnection *c, int fwd); | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Resets the connection timeout task, some other message has done the | ||
403 | * task's job. | ||
404 | * - For the first peer on the direction this means to send | ||
405 | * a keepalive or a path confirmation message (either create or ACK). | ||
406 | * - For all other peers, this means to destroy the connection, | ||
407 | * due to lack of activity. | ||
408 | * Starts the timeout if no timeout was running (connection just created). | ||
409 | * | ||
410 | * @param c Connection whose timeout to reset. | ||
411 | * @param fwd Is this forward? | ||
412 | */ | ||
413 | static void | ||
414 | connection_reset_timeout (struct CadetConnection *c, int fwd); | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Get string description for tunnel state. Reentrant. | ||
419 | * | ||
420 | * @param s Tunnel state. | ||
421 | * | ||
422 | * @return String representation. | ||
423 | */ | ||
424 | static const char * | ||
425 | GCC_state2s (enum CadetConnectionState s) | ||
426 | { | ||
427 | switch (s) | ||
428 | { | ||
429 | case CADET_CONNECTION_NEW: | ||
430 | return "CADET_CONNECTION_NEW"; | ||
431 | case CADET_CONNECTION_SENT: | ||
432 | return "CADET_CONNECTION_SENT"; | ||
433 | case CADET_CONNECTION_ACK: | ||
434 | return "CADET_CONNECTION_ACK"; | ||
435 | case CADET_CONNECTION_READY: | ||
436 | return "CADET_CONNECTION_READY"; | ||
437 | case CADET_CONNECTION_DESTROYED: | ||
438 | return "CADET_CONNECTION_DESTROYED"; | ||
439 | case CADET_CONNECTION_BROKEN: | ||
440 | return "CADET_CONNECTION_BROKEN"; | ||
441 | default: | ||
442 | GNUNET_break (0); | ||
443 | LOG (GNUNET_ERROR_TYPE_ERROR, " conn state %u unknown!\n", s); | ||
444 | return "CADET_CONNECTION_STATE_ERROR"; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | 169 | /** |
450 | * Initialize a Flow Control structure to the initial state. | 170 | * Lookup a connection by its identifier. |
451 | * | 171 | * |
452 | * @param fc Flow Control structure to initialize. | 172 | * @param cid identifier to resolve |
173 | * @return NULL if connection was not found | ||
453 | */ | 174 | */ |
454 | static void | 175 | struct CadetConnection * |
455 | fc_init (struct CadetFlowControl *fc) | 176 | GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
456 | { | ||
457 | fc->next_pid.pid = 0; | ||
458 | fc->last_pid_sent.pid = htonl (UINT32_MAX); | ||
459 | fc->last_pid_recv.pid = htonl (UINT32_MAX); | ||
460 | fc->last_ack_sent.pid = (uint32_t) 0; | ||
461 | fc->last_ack_recv.pid = (uint32_t) 0; | ||
462 | fc->poll_task = NULL; | ||
463 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
464 | fc->queue_n = 0; | ||
465 | fc->queue_max = (max_msgs_queue / max_connections) + 1; | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Find a connection. | ||
471 | * | ||
472 | * @param cid Connection ID. | ||
473 | * | ||
474 | * @return conntection with the given ID @cid or NULL if not found. | ||
475 | */ | ||
476 | static struct CadetConnection * | ||
477 | connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
478 | { | 177 | { |
479 | return GNUNET_CONTAINER_multishortmap_get (connections, | 178 | return GNUNET_CONTAINER_multishortmap_get (connections, |
480 | &cid->connection_of_tunnel); | 179 | &cid->connection_of_tunnel); |
@@ -482,3232 +181,911 @@ connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | |||
482 | 181 | ||
483 | 182 | ||
484 | /** | 183 | /** |
485 | * Change the connection state. Cannot change a connection marked as destroyed. | 184 | * Update the connection state. Also triggers the necessary |
185 | * MQM notifications. | ||
486 | * | 186 | * |
487 | * @param c Connection to change. | 187 | * @param cc connection to update the state for |
488 | * @param state New state to set. | 188 | * @param new_state new state for @a cc |
189 | * @param new_mqm_ready new `mqm_ready` state for @a cc | ||
489 | */ | 190 | */ |
490 | static void | 191 | static void |
491 | connection_change_state (struct CadetConnection* c, | 192 | update_state (struct CadetConnection *cc, |
492 | enum CadetConnectionState state) | 193 | enum CadetConnectionState new_state, |
194 | int new_mqm_ready) | ||
493 | { | 195 | { |
494 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 196 | int old_ready; |
495 | "Connection %s state %s -> %s\n", | 197 | int new_ready; |
496 | GCC_2s (c), GCC_state2s (c->state), GCC_state2s (state)); | ||
497 | if (CADET_CONNECTION_DESTROYED <= c->state) /* Destroyed or broken. */ | ||
498 | { | ||
499 | LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n"); | ||
500 | return; | ||
501 | } | ||
502 | c->state = state; | ||
503 | if (CADET_CONNECTION_READY == state) | ||
504 | c->create_retry = 1; | ||
505 | } | ||
506 | |||
507 | 198 | ||
508 | /** | 199 | if ( (new_state == cc->state) && |
509 | * Mark a connection as "destroyed", to send all pending traffic and freeing | 200 | (new_mqm_ready == cc->mqm_ready) ) |
510 | * all associated resources, without accepting new status changes on it. | 201 | return; /* no change, nothing to do */ |
511 | * | 202 | old_ready = ( (CADET_CONNECTION_READY == cc->state) && |
512 | * @param c Connection to mark as destroyed. | 203 | (GNUNET_YES == cc->mqm_ready) ); |
513 | */ | 204 | new_ready = ( (CADET_CONNECTION_READY == new_state) && |
514 | static void | 205 | (GNUNET_YES == new_mqm_ready) ); |
515 | mark_destroyed (struct CadetConnection *c) | 206 | cc->state = new_state; |
516 | { | 207 | cc->mqm_ready = new_mqm_ready; |
517 | c->destroy = GNUNET_YES; | 208 | if (old_ready != new_ready) |
518 | connection_change_state (c, CADET_CONNECTION_DESTROYED); | 209 | cc->ready_cb (cc->ready_cb_cls, |
210 | new_ready); | ||
519 | } | 211 | } |
520 | 212 | ||
521 | 213 | ||
522 | /** | 214 | /** |
523 | * Function called if a connection has been stalled for a while, | 215 | * Destroy a connection, part of the internal implementation. Called |
524 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | 216 | * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel(). |
525 | * | ||
526 | * @param cls Closure (poll ctx). | ||
527 | */ | ||
528 | static void | ||
529 | send_poll (void *cls); | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Send an ACK on the connection, informing the predecessor about | ||
534 | * the available buffer space. Should not be called in case the peer | ||
535 | * is origin (no predecessor) in the @c fwd direction. | ||
536 | * | ||
537 | * Note that for fwd ack, the FWD mean forward *traffic* (root->dest), | ||
538 | * the ACK itself goes "back" (dest->root). | ||
539 | * | 217 | * |
540 | * @param c Connection on which to send the ACK. | 218 | * @param cc connection to destroy |
541 | * @param buffer How much space free to advertise? | ||
542 | * @param fwd Is this FWD ACK? (Going dest -> root) | ||
543 | * @param force Don't optimize out. | ||
544 | */ | 219 | */ |
545 | static void | 220 | static void |
546 | send_ack (struct CadetConnection *c, | 221 | GCC_destroy (struct CadetConnection *cc) |
547 | unsigned int buffer, | ||
548 | int fwd, | ||
549 | int force) | ||
550 | { | 222 | { |
551 | static struct CadetEncryptedMessageIdentifier zero; | ||
552 | struct CadetFlowControl *next_fc; | ||
553 | struct CadetFlowControl *prev_fc; | ||
554 | struct GNUNET_CADET_ConnectionEncryptedAckMessage msg; | ||
555 | struct CadetEncryptedMessageIdentifier ack_cemi; | ||
556 | int delta; | ||
557 | |||
558 | GCC_check_connections (); | ||
559 | GNUNET_assert (GNUNET_NO == GCC_is_origin (c, fwd)); | ||
560 | |||
561 | next_fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
562 | prev_fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
563 | |||
564 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send %s ack on %s\n", | ||
565 | GC_f2s (fwd), GCC_2s (c)); | ||
566 | |||
567 | /* Check if we need to transmit the ACK. */ | ||
568 | delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid); | ||
569 | if (3 < delta && buffer < delta && GNUNET_NO == force) | ||
570 | { | ||
571 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n"); | ||
572 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
573 | " last pid recv: %u, last ack sent: %u\n", | ||
574 | ntohl (prev_fc->last_pid_recv.pid), | ||
575 | ntohl (prev_fc->last_ack_sent.pid)); | ||
576 | GCC_check_connections (); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | /* Ok, ACK might be necessary, what PID to ACK? */ | ||
581 | ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer); | ||
582 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 223 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
583 | " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n", | 224 | "Destroying %s\n", |
584 | ntohl (ack_cemi.pid), | 225 | GCC_2s (cc)); |
585 | ntohl (prev_fc->last_pid_recv.pid), | 226 | if (NULL != cc->mq_man) |
586 | ntohl (prev_fc->last_ack_sent.pid), | ||
587 | next_fc->queue_max, next_fc->queue_n); | ||
588 | if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) && | ||
589 | (GNUNET_NO == force) ) | ||
590 | { | ||
591 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); | ||
592 | GCC_check_connections (); | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | /* Check if message is already in queue */ | ||
597 | if (NULL != prev_fc->ack_msg) | ||
598 | { | ||
599 | if (GC_is_pid_bigger (ntohl (ack_cemi.pid), | ||
600 | ntohl (prev_fc->last_ack_sent.pid))) | ||
601 | { | ||
602 | LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); | ||
603 | GCC_cancel (prev_fc->ack_msg); | ||
604 | /* GCC_cancel triggers ack_sent(), which clears fc->ack_msg */ | ||
605 | } | ||
606 | else | ||
607 | { | ||
608 | LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n"); | ||
609 | GCC_check_connections (); | ||
610 | return; | ||
611 | } | ||
612 | } | ||
613 | GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid), | ||
614 | ntohl (prev_fc->last_ack_sent.pid))); | ||
615 | prev_fc->last_ack_sent = ack_cemi; | ||
616 | |||
617 | /* Build ACK message and send on conn */ | ||
618 | msg.header.size = htons (sizeof (msg)); | ||
619 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK); | ||
620 | msg.cemi_max = ack_cemi; | ||
621 | msg.cid = c->id; | ||
622 | |||
623 | prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header, | ||
624 | UINT16_MAX, | ||
625 | zero, | ||
626 | c, | ||
627 | !fwd, | ||
628 | GNUNET_YES, | ||
629 | NULL, NULL); | ||
630 | GNUNET_assert (NULL != prev_fc->ack_msg); | ||
631 | GCC_check_connections (); | ||
632 | } | ||
633 | |||
634 | |||
635 | /** | ||
636 | * Update performance information if we are a connection's endpoint. | ||
637 | * | ||
638 | * @param c Connection to update. | ||
639 | * @param wait How much time did we wait to send the last message. | ||
640 | * @param size Size of the last message. | ||
641 | */ | ||
642 | static void | ||
643 | update_perf (struct CadetConnection *c, | ||
644 | struct GNUNET_TIME_Relative wait, | ||
645 | uint16_t size) | ||
646 | { | ||
647 | struct CadetConnectionPerformance *p; | ||
648 | double usecsperbyte; | ||
649 | |||
650 | if (NULL == c->perf) | ||
651 | return; /* Only endpoints are interested in timing. */ | ||
652 | |||
653 | p = c->perf; | ||
654 | usecsperbyte = ((double) wait.rel_value_us) / size; | ||
655 | if (p->size == AVG_MSGS) | ||
656 | { | ||
657 | /* Array is full. Substract oldest value, add new one and store. */ | ||
658 | p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
659 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
660 | p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | /* Array not yet full. Add current value to avg and store. */ | ||
665 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
666 | p->avg *= p->size; | ||
667 | p->avg += p->usecsperbyte[p->idx]; | ||
668 | p->size++; | ||
669 | p->avg /= p->size; | ||
670 | } | ||
671 | p->idx = (p->idx + 1) % AVG_MSGS; | ||
672 | } | ||
673 | |||
674 | |||
675 | /** | ||
676 | * Callback called when a connection queued message is sent. | ||
677 | * | ||
678 | * Calculates the average time and connection packet tracking. | ||
679 | * | ||
680 | * @param cls Closure (ConnectionQueue Handle), can be NULL. | ||
681 | * @param c Connection this message was on. | ||
682 | * @param fwd Was this a FWD going message? | ||
683 | * @param sent Was it really sent? (Could have been canceled) | ||
684 | * @param type Type of message sent. | ||
685 | * @param payload_type Type of payload, if applicable. | ||
686 | * @param pid Message ID, or 0 if not applicable (create, destroy, etc). | ||
687 | * @param size Size of the message. | ||
688 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
689 | */ | ||
690 | static void | ||
691 | conn_message_sent (void *cls, | ||
692 | struct CadetConnection *c, | ||
693 | int fwd, | ||
694 | int sent, | ||
695 | uint16_t type, | ||
696 | uint16_t payload_type, | ||
697 | struct CadetEncryptedMessageIdentifier pid, | ||
698 | size_t size, | ||
699 | struct GNUNET_TIME_Relative wait) | ||
700 | { | ||
701 | struct CadetConnectionQueue *q = cls; | ||
702 | struct CadetFlowControl *fc; | ||
703 | int forced; | ||
704 | |||
705 | GCC_check_connections (); | ||
706 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
707 | ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n", | ||
708 | GC_m2s (type), GC_m2s (payload_type), | ||
709 | ntohl (pid.pid), | ||
710 | GCC_2s (c), | ||
711 | c, | ||
712 | GC_f2s (fwd), size, | ||
713 | GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES)); | ||
714 | |||
715 | /* If c is NULL, nothing to update. */ | ||
716 | if (NULL == c) | ||
717 | { | ||
718 | if (type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
719 | && type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY) | ||
720 | { | ||
721 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", | ||
722 | GC_m2s (type)); | ||
723 | } | ||
724 | GCC_check_connections (); | ||
725 | return; | ||
726 | } | ||
727 | |||
728 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n", | ||
729 | sent ? "" : "not ", GC_f2s (fwd), | ||
730 | GC_m2s (type), GC_m2s (payload_type), | ||
731 | ntohl (pid.pid)); | ||
732 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | ||
733 | |||
734 | /* Update flow control info. */ | ||
735 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
736 | |||
737 | if (NULL != q) | ||
738 | { | 227 | { |
739 | GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q); | 228 | GCP_request_mq_cancel (cc->mq_man, |
740 | forced = q->forced; | 229 | NULL); |
741 | if (NULL != q->cont) | 230 | cc->mq_man = NULL; |
742 | { | ||
743 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n"); | ||
744 | q->cont (q->cont_cls, c, q, type, fwd, size); | ||
745 | } | ||
746 | GNUNET_free (q); | ||
747 | } | 231 | } |
748 | else /* CONN_CREATE or CONN_ACK */ | 232 | if (NULL != cc->task) |
749 | { | 233 | { |
750 | GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type); | 234 | GNUNET_SCHEDULER_cancel (cc->task); |
751 | forced = GNUNET_YES; | 235 | cc->task = NULL; |
752 | } | 236 | } |
753 | 237 | if (NULL != cc->keepalive_qe) | |
754 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); | ||
755 | c->pending_messages--; | ||
756 | if ( (GNUNET_YES == c->destroy) && | ||
757 | (0 == c->pending_messages) ) | ||
758 | { | 238 | { |
759 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 239 | GCT_send_cancel (cc->keepalive_qe); |
760 | "! destroying connection!\n"); | 240 | cc->keepalive_qe = NULL; |
761 | GCC_destroy (c); | ||
762 | GCC_check_connections (); | ||
763 | return; | ||
764 | } | 241 | } |
765 | 242 | GCPP_del_connection (cc->path, | |
766 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ | 243 | cc->off, |
767 | switch (type) | 244 | cc); |
768 | { | 245 | for (unsigned int i=0;i<cc->off;i++) |
769 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | 246 | GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, |
770 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | 247 | i), |
771 | c->maintenance_q = NULL; | 248 | cc); |
772 | /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ | 249 | GNUNET_assert (GNUNET_YES == |
773 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) | 250 | GNUNET_CONTAINER_multishortmap_remove (connections, |
774 | schedule_next_keepalive (c, fwd); | 251 | &GCC_get_id (cc)->connection_of_tunnel, |
775 | break; | 252 | cc)); |
776 | 253 | GNUNET_free (cc); | |
777 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
778 | if (GNUNET_YES == sent) | ||
779 | { | ||
780 | fc->last_pid_sent = pid; | ||
781 | if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1, | ||
782 | ntohl (fc->last_ack_recv.pid)) ) | ||
783 | GCC_start_poll (c, fwd); | ||
784 | GCC_send_ack (c, fwd, GNUNET_NO); | ||
785 | connection_reset_timeout (c, fwd); | ||
786 | } | ||
787 | |||
788 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); | ||
789 | if (GNUNET_NO == forced) | ||
790 | { | ||
791 | fc->queue_n--; | ||
792 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
793 | "! accounting pid %u\n", | ||
794 | ntohl (fc->last_pid_sent.pid)); | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
799 | "! forced, Q_N not accounting pid %u\n", | ||
800 | ntohl (fc->last_pid_sent.pid)); | ||
801 | } | ||
802 | break; | ||
803 | |||
804 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
805 | if (GNUNET_YES == sent) | ||
806 | connection_reset_timeout (c, fwd); | ||
807 | break; | ||
808 | |||
809 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
810 | fc->poll_msg = NULL; | ||
811 | if (2 == c->destroy) | ||
812 | { | ||
813 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL canceled on shutdown\n"); | ||
814 | return; | ||
815 | } | ||
816 | if (0 == fc->queue_max) | ||
817 | { | ||
818 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL cancelled: neighbor disconnected\n"); | ||
819 | return; | ||
820 | } | ||
821 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL sent for %s, scheduling new one!\n", | ||
822 | GCC_2s (c)); | ||
823 | GNUNET_assert (NULL == fc->poll_task); | ||
824 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); | ||
825 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
826 | &send_poll, fc); | ||
827 | LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); | ||
828 | break; | ||
829 | |||
830 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
831 | fc->ack_msg = NULL; | ||
832 | break; | ||
833 | |||
834 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
835 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
836 | break; | ||
837 | |||
838 | default: | ||
839 | LOG (GNUNET_ERROR_TYPE_ERROR, "%s unknown\n", GC_m2s (type)); | ||
840 | GNUNET_break (0); | ||
841 | break; | ||
842 | } | ||
843 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); | ||
844 | |||
845 | update_perf (c, wait, size); | ||
846 | GCC_check_connections (); | ||
847 | } | ||
848 | |||
849 | |||
850 | /** | ||
851 | * Get the previous hop in a connection | ||
852 | * | ||
853 | * @param c Connection. | ||
854 | * | ||
855 | * @return Previous peer in the connection. | ||
856 | */ | ||
857 | static struct CadetPeer * | ||
858 | get_prev_hop (const struct CadetConnection *c) | ||
859 | { | ||
860 | GNUNET_PEER_Id id; | ||
861 | |||
862 | if (NULL == c->path) | ||
863 | return NULL; | ||
864 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
865 | " get prev hop %s [%u/%u]\n", | ||
866 | GCC_2s (c), c->own_pos, c->path->length); | ||
867 | if (0 == c->own_pos || c->path->length < 2) | ||
868 | id = c->path->peers[0]; | ||
869 | else | ||
870 | id = c->path->peers[c->own_pos - 1]; | ||
871 | |||
872 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
873 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
874 | |||
875 | return GCP_get_short (id, GNUNET_YES); | ||
876 | } | ||
877 | |||
878 | |||
879 | /** | ||
880 | * Get the next hop in a connection | ||
881 | * | ||
882 | * @param c Connection. | ||
883 | * | ||
884 | * @return Next peer in the connection. | ||
885 | */ | ||
886 | static struct CadetPeer * | ||
887 | get_next_hop (const struct CadetConnection *c) | ||
888 | { | ||
889 | GNUNET_PEER_Id id; | ||
890 | |||
891 | if (NULL == c->path) | ||
892 | return NULL; | ||
893 | |||
894 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n", | ||
895 | GCC_2s (c), c->own_pos, c->path->length); | ||
896 | if ((c->path->length - 1) == c->own_pos || c->path->length < 2) | ||
897 | id = c->path->peers[c->path->length - 1]; | ||
898 | else | ||
899 | id = c->path->peers[c->own_pos + 1]; | ||
900 | |||
901 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
902 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
903 | |||
904 | return GCP_get_short (id, GNUNET_YES); | ||
905 | } | 254 | } |
906 | 255 | ||
907 | 256 | ||
908 | /** | ||
909 | * Check that the direct neighbours (previous and next hop) | ||
910 | * are properly associated with this connection. | ||
911 | * | ||
912 | * @param c connection to check | ||
913 | */ | ||
914 | static void | ||
915 | check_neighbours (const struct CadetConnection *c) | ||
916 | { | ||
917 | if (NULL == c->path) | ||
918 | return; /* nothing to check */ | ||
919 | GCP_check_connection (get_next_hop (c), c); | ||
920 | GCP_check_connection (get_prev_hop (c), c); | ||
921 | } | ||
922 | |||
923 | 257 | ||
924 | /** | 258 | /** |
925 | * Helper for #GCC_check_connections(). Calls #check_neighbours(). | 259 | * Destroy a connection, called when the CORE layer is already done |
260 | * (i.e. has received a BROKEN message), but if we still have to | ||
261 | * communicate the destruction of the connection to the tunnel (if one | ||
262 | * exists). | ||
926 | * | 263 | * |
927 | * @param cls NULL | 264 | * @param cc connection to destroy |
928 | * @param key ignored | ||
929 | * @param value the `struct CadetConnection` to check | ||
930 | * @return #GNUNET_OK (continue to iterate) | ||
931 | */ | ||
932 | static int | ||
933 | check_connection (void *cls, | ||
934 | const struct GNUNET_ShortHashCode *key, | ||
935 | void *value) | ||
936 | { | ||
937 | struct CadetConnection *c = value; | ||
938 | |||
939 | check_neighbours (c); | ||
940 | return GNUNET_OK; | ||
941 | } | ||
942 | |||
943 | |||
944 | /** | ||
945 | * Check invariants for all connections using #check_neighbours(). | ||
946 | */ | 265 | */ |
947 | void | 266 | void |
948 | GCC_check_connections () | 267 | GCC_destroy_without_core (struct CadetConnection *cc) |
949 | { | ||
950 | if (0 == CHECK_INVARIANTS) | ||
951 | return; | ||
952 | if (NULL == connections) | ||
953 | return; | ||
954 | GNUNET_CONTAINER_multishortmap_iterate (connections, | ||
955 | &check_connection, | ||
956 | NULL); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Get the hop in a connection. | ||
962 | * | ||
963 | * @param c Connection. | ||
964 | * @param fwd Next in the FWD direction? | ||
965 | * | ||
966 | * @return Next peer in the connection. | ||
967 | */ | ||
968 | static struct CadetPeer * | ||
969 | get_hop (struct CadetConnection *c, int fwd) | ||
970 | { | ||
971 | return (fwd) ? get_next_hop (c) : get_prev_hop (c); | ||
972 | } | ||
973 | |||
974 | |||
975 | /** | ||
976 | * Get a bit mask for a message received out-of-order. | ||
977 | * | ||
978 | * @param last_pid_recv Last PID we received prior to the out-of-order. | ||
979 | * @param ooo_pid PID of the out-of-order message. | ||
980 | */ | ||
981 | static uint32_t | ||
982 | get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv, | ||
983 | struct CadetEncryptedMessageIdentifier ooo_pid) | ||
984 | { | ||
985 | // FIXME: should assert that the delta is in range... | ||
986 | return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid)); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Check is an out-of-order message is ok: | ||
992 | * - at most 31 messages behind. | ||
993 | * - not duplicate. | ||
994 | * | ||
995 | * @param last_pid_recv Last in-order PID received. | ||
996 | */ | ||
997 | static int | ||
998 | is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv, | ||
999 | struct CadetEncryptedMessageIdentifier ooo_pid, | ||
1000 | uint32_t ooo_bitmap) | ||
1001 | { | ||
1002 | uint32_t mask; | ||
1003 | |||
1004 | if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31, | ||
1005 | ntohl (ooo_pid.pid))) | ||
1006 | return GNUNET_NO; | ||
1007 | |||
1008 | mask = get_recv_bitmask (last_pid_recv, | ||
1009 | ooo_pid); | ||
1010 | if (0 != (ooo_bitmap & mask)) | ||
1011 | return GNUNET_NO; | ||
1012 | |||
1013 | return GNUNET_YES; | ||
1014 | } | ||
1015 | |||
1016 | |||
1017 | /** | ||
1018 | * Is traffic coming from this sender 'FWD' traffic? | ||
1019 | * | ||
1020 | * @param c Connection to check. | ||
1021 | * @param sender Short peer identity of neighbor. | ||
1022 | * | ||
1023 | * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore | ||
1024 | * the traffic is 'FWD'. | ||
1025 | * #GNUNET_NO for BCK. | ||
1026 | * #GNUNET_SYSERR for errors (sender isn't a hop in the connection). | ||
1027 | */ | ||
1028 | static int | ||
1029 | is_fwd (const struct CadetConnection *c, | ||
1030 | const struct CadetPeer *sender) | ||
1031 | { | ||
1032 | GNUNET_PEER_Id id; | ||
1033 | |||
1034 | id = GCP_get_short_id (sender); | ||
1035 | if (GCP_get_short_id (get_prev_hop (c)) == id) | ||
1036 | return GNUNET_YES; | ||
1037 | |||
1038 | if (GCP_get_short_id (get_next_hop (c)) == id) | ||
1039 | return GNUNET_NO; | ||
1040 | |||
1041 | return GNUNET_SYSERR; | ||
1042 | } | ||
1043 | |||
1044 | |||
1045 | /** | ||
1046 | * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE | ||
1047 | * or a first CONNECTION_ACK directed to us. | ||
1048 | * | ||
1049 | * @param c Connection to confirm. | ||
1050 | * @param fwd Should we send it FWD? (root->dest) | ||
1051 | * (First (~SYNACK) goes BCK, second (~ACK) goes FWD) | ||
1052 | */ | ||
1053 | static void | ||
1054 | send_connection_ack (struct CadetConnection *c, int fwd) | ||
1055 | { | ||
1056 | static struct CadetEncryptedMessageIdentifier zero; | ||
1057 | struct GNUNET_CADET_ConnectionCreateAckMessage msg; | ||
1058 | struct CadetTunnel *t; | ||
1059 | const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateAckMessage); | ||
1060 | const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK; | ||
1061 | |||
1062 | GCC_check_connections (); | ||
1063 | t = c->t; | ||
1064 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1065 | "==> %s ({ C %s ACK} 0) on conn %s (%p) %s [%5u]\n", | ||
1066 | GC_m2s (type), GC_f2s (!fwd), GCC_2s (c), c, GC_f2s (fwd), size); | ||
1067 | |||
1068 | msg.header.size = htons (size); | ||
1069 | msg.header.type = htons (type); | ||
1070 | msg.reserved = htonl (0); | ||
1071 | msg.cid = c->id; | ||
1072 | |||
1073 | GNUNET_assert (NULL == c->maintenance_q); | ||
1074 | c->maintenance_q = GCP_send (get_hop (c, fwd), | ||
1075 | &msg.header, | ||
1076 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
1077 | zero, | ||
1078 | c, | ||
1079 | fwd, | ||
1080 | &conn_message_sent, NULL); | ||
1081 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n", | ||
1082 | c, c->pending_messages); | ||
1083 | c->pending_messages++; | ||
1084 | |||
1085 | if (CADET_TUNNEL_NEW == GCT_get_cstate (t)) | ||
1086 | GCT_change_cstate (t, CADET_TUNNEL_WAITING); | ||
1087 | if (CADET_CONNECTION_READY != c->state) | ||
1088 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
1089 | GCC_check_connections (); | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * Send a notification that a connection is broken. | ||
1095 | * | ||
1096 | * @param c Connection that is broken. | ||
1097 | * @param id1 Peer that has disconnected. | ||
1098 | * @param id2 Peer that has disconnected. | ||
1099 | * @param fwd Direction towards which to send it. | ||
1100 | */ | ||
1101 | static void | ||
1102 | send_broken (struct CadetConnection *c, | ||
1103 | const struct GNUNET_PeerIdentity *id1, | ||
1104 | const struct GNUNET_PeerIdentity *id2, | ||
1105 | int fwd) | ||
1106 | { | ||
1107 | static struct CadetEncryptedMessageIdentifier zero; | ||
1108 | struct GNUNET_CADET_ConnectionBrokenMessage msg; | ||
1109 | |||
1110 | GCC_check_connections (); | ||
1111 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage)); | ||
1112 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
1113 | msg.cid = c->id; | ||
1114 | msg.reserved = htonl (0); | ||
1115 | msg.peer1 = *id1; | ||
1116 | msg.peer2 = *id2; | ||
1117 | (void) GCC_send_prebuilt_message (&msg.header, | ||
1118 | UINT16_MAX, | ||
1119 | zero, | ||
1120 | c, | ||
1121 | fwd, | ||
1122 | GNUNET_YES, | ||
1123 | NULL, NULL); | ||
1124 | GCC_check_connections (); | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | /** | ||
1129 | * Send a notification that a connection is broken, when a connection | ||
1130 | * isn't even known to the local peer or soon to be destroyed. | ||
1131 | * | ||
1132 | * @param connection_id Connection ID. | ||
1133 | * @param id1 Peer that has disconnected, probably local peer. | ||
1134 | * @param id2 Peer that has disconnected can be NULL if unknown. | ||
1135 | * @param neighbor Peer to notify (neighbor who sent the connection). | ||
1136 | */ | ||
1137 | static void | ||
1138 | send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id, | ||
1139 | const struct GNUNET_PeerIdentity *id1, | ||
1140 | const struct GNUNET_PeerIdentity *id2, | ||
1141 | struct CadetPeer *neighbor) | ||
1142 | { | ||
1143 | static struct CadetEncryptedMessageIdentifier zero; | ||
1144 | struct GNUNET_CADET_ConnectionBrokenMessage msg; | ||
1145 | |||
1146 | GCC_check_connections (); | ||
1147 | LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n", | ||
1148 | GNUNET_sh2s (&connection_id->connection_of_tunnel)); | ||
1149 | |||
1150 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage)); | ||
1151 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
1152 | msg.cid = *connection_id; | ||
1153 | msg.reserved = htonl (0); | ||
1154 | msg.peer1 = *id1; | ||
1155 | if (NULL != id2) | ||
1156 | msg.peer2 = *id2; | ||
1157 | else | ||
1158 | memset (&msg.peer2, 0, sizeof (msg.peer2)); | ||
1159 | GNUNET_assert (NULL != GCP_send (neighbor, | ||
1160 | &msg.header, | ||
1161 | UINT16_MAX, | ||
1162 | zero, | ||
1163 | NULL, | ||
1164 | GNUNET_SYSERR, /* connection, fwd */ | ||
1165 | NULL, NULL)); /* continuation */ | ||
1166 | GCC_check_connections (); | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1171 | * Send keepalive packets for a connection. | ||
1172 | * | ||
1173 | * @param c Connection to keep alive.. | ||
1174 | * @param fwd Is this a FWD keepalive? (owner -> dest). | ||
1175 | */ | ||
1176 | static void | ||
1177 | send_connection_keepalive (struct CadetConnection *c, int fwd) | ||
1178 | { | 268 | { |
1179 | struct GNUNET_MessageHeader msg; | 269 | if (NULL != cc->ct) |
1180 | struct CadetFlowControl *fc; | ||
1181 | int tunnel_ready; | ||
1182 | |||
1183 | GCC_check_connections (); | ||
1184 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1185 | "keepalive %s for connection %s\n", | ||
1186 | GC_f2s (fwd), GCC_2s (c)); | ||
1187 | |||
1188 | GNUNET_assert (NULL != c->t); | ||
1189 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
1190 | tunnel_ready = GNUNET_YES == GCT_has_queued_traffic (c->t) | ||
1191 | && CADET_TUNNEL_KEY_OK <= GCT_get_estate (c->t); | ||
1192 | if (0 < fc->queue_n || tunnel_ready) | ||
1193 | { | 270 | { |
1194 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); | 271 | GCT_connection_lost (cc->ct); |
1195 | return; | 272 | cc->ct = NULL; |
1196 | } | 273 | } |
1197 | 274 | GCC_destroy (cc); | |
1198 | GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO); | ||
1199 | |||
1200 | GNUNET_assert (NULL != c->t); | ||
1201 | msg.size = htons (sizeof (msg)); | ||
1202 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE); | ||
1203 | |||
1204 | GNUNET_assert (NULL == | ||
1205 | GCT_send_prebuilt_message (&msg, c->t, c, | ||
1206 | GNUNET_NO, NULL, NULL)); | ||
1207 | GCC_check_connections (); | ||
1208 | } | ||
1209 | |||
1210 | |||
1211 | /** | ||
1212 | * Send CONNECTION_{CREATE/ACK} packets for a connection. | ||
1213 | * | ||
1214 | * @param c Connection for which to send the message. | ||
1215 | * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK. | ||
1216 | */ | ||
1217 | static void | ||
1218 | connection_recreate (struct CadetConnection *c, int fwd) | ||
1219 | { | ||
1220 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1221 | "sending connection recreate\n"); | ||
1222 | if (fwd) | ||
1223 | GCC_send_create (c); | ||
1224 | else | ||
1225 | send_connection_ack (c, GNUNET_NO); | ||
1226 | } | 275 | } |
1227 | 276 | ||
1228 | 277 | ||
1229 | /** | 278 | /** |
1230 | * Generic connection timer management. | 279 | * Destroy a connection, called if the tunnel association with the |
1231 | * Depending on the role of the peer in the connection will send the | 280 | * connection was already broken, but we still need to notify the CORE |
1232 | * appropriate message (build or keepalive) | 281 | * layer about the breakage. |
1233 | * | 282 | * |
1234 | * @param c Conncetion to maintain. | 283 | * @param cc connection to destroy |
1235 | * @param fwd Is FWD? | ||
1236 | */ | 284 | */ |
1237 | static void | 285 | void |
1238 | connection_maintain (struct CadetConnection *c, int fwd) | 286 | GCC_destroy_without_tunnel (struct CadetConnection *cc) |
1239 | { | 287 | { |
1240 | if (GNUNET_NO != c->destroy) | 288 | cc->ct = NULL; |
289 | if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) && | ||
290 | (NULL != cc->mq_man) ) | ||
1241 | { | 291 | { |
1242 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, being destroyed\n"); | 292 | struct GNUNET_MQ_Envelope *env; |
1243 | return; | 293 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; |
1244 | } | ||
1245 | |||
1246 | if (NULL == c->t) | ||
1247 | { | ||
1248 | GNUNET_break (0); | ||
1249 | GCC_debug (c, GNUNET_ERROR_TYPE_ERROR); | ||
1250 | return; | ||
1251 | } | ||
1252 | 294 | ||
1253 | if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (c->t)) | 295 | /* Need to notify next hop that we are down. */ |
1254 | { | 296 | env = GNUNET_MQ_msg (destroy_msg, |
1255 | /* If status is SEARCHING, why is there a connection? Should be WAITING */ | 297 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); |
1256 | GNUNET_break (0); | 298 | destroy_msg->cid = cc->cid; |
1257 | GCT_debug (c->t, GNUNET_ERROR_TYPE_ERROR); | 299 | GCP_request_mq_cancel (cc->mq_man, |
1258 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, tunnel SEARCHING\n"); | 300 | env); |
1259 | schedule_next_keepalive (c, fwd); | 301 | cc->mq_man = NULL; |
1260 | return; | ||
1261 | } | ||
1262 | switch (c->state) | ||
1263 | { | ||
1264 | case CADET_CONNECTION_NEW: | ||
1265 | GNUNET_break (0); | ||
1266 | /* fall-through */ | ||
1267 | case CADET_CONNECTION_SENT: | ||
1268 | connection_recreate (c, fwd); | ||
1269 | break; | ||
1270 | case CADET_CONNECTION_READY: | ||
1271 | send_connection_keepalive (c, fwd); | ||
1272 | break; | ||
1273 | default: | ||
1274 | break; | ||
1275 | } | 302 | } |
303 | GCC_destroy (cc); | ||
1276 | } | 304 | } |
1277 | 305 | ||
1278 | 306 | ||
1279 | /** | 307 | /** |
1280 | * Keep the connection alive. | 308 | * Return the tunnel associated with this connection. |
1281 | * | 309 | * |
1282 | * @param c Connection to keep alive. | 310 | * @param cc connection to query |
1283 | * @param fwd Direction. | 311 | * @return corresponding entry in the tunnel's connection list |
1284 | */ | 312 | */ |
1285 | static void | 313 | struct CadetTConnection * |
1286 | connection_keepalive (struct CadetConnection *c, | 314 | GCC_get_ct (struct CadetConnection *cc) |
1287 | int fwd) | ||
1288 | { | 315 | { |
1289 | GCC_check_connections (); | 316 | return cc->ct; |
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "%s keepalive for %s\n", | ||
1292 | GC_f2s (fwd), GCC_2s (c)); | ||
1293 | |||
1294 | if (fwd) | ||
1295 | c->fwd_maintenance_task = NULL; | ||
1296 | else | ||
1297 | c->bck_maintenance_task = NULL; | ||
1298 | connection_maintain (c, fwd); | ||
1299 | GCC_check_connections (); | ||
1300 | /* Next execution will be scheduled by message_sent or _maintain*/ | ||
1301 | } | 317 | } |
1302 | 318 | ||
1303 | 319 | ||
1304 | /** | 320 | /** |
1305 | * Keep the connection alive in the FWD direction. | 321 | * Obtain performance @a metrics from @a cc. |
1306 | * | 322 | * |
1307 | * @param cls Closure (connection to keepalive). | 323 | * @param cc connection to query |
324 | * @return the metrics | ||
1308 | */ | 325 | */ |
1309 | static void | 326 | const struct CadetConnectionMetrics * |
1310 | connection_fwd_keepalive (void *cls) | 327 | GCC_get_metrics (struct CadetConnection *cc) |
1311 | { | 328 | { |
1312 | struct CadetConnection *c = cls; | 329 | return &cc->metrics; |
1313 | |||
1314 | GCC_check_connections (); | ||
1315 | connection_keepalive (c, | ||
1316 | GNUNET_YES); | ||
1317 | GCC_check_connections (); | ||
1318 | } | 330 | } |
1319 | 331 | ||
1320 | 332 | ||
1321 | /** | 333 | /** |
1322 | * Keep the connection alive in the BCK direction. | 334 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the |
335 | * tunnel to prevent it from timing out. | ||
1323 | * | 336 | * |
1324 | * @param cls Closure (connection to keepalive). | 337 | * @param cls the `struct CadetConnection` to keep alive. |
1325 | */ | 338 | */ |
1326 | static void | 339 | static void |
1327 | connection_bck_keepalive (void *cls) | 340 | send_keepalive (void *cls); |
1328 | { | ||
1329 | struct CadetConnection *c = cls; | ||
1330 | |||
1331 | GCC_check_connections (); | ||
1332 | connection_keepalive (c, | ||
1333 | GNUNET_NO); | ||
1334 | GCC_check_connections (); | ||
1335 | } | ||
1336 | 341 | ||
1337 | 342 | ||
1338 | /** | 343 | /** |
1339 | * Schedule next keepalive task, taking in consideration | 344 | * Keepalive was transmitted. Remember this, and possibly |
1340 | * the connection state and number of retries. | 345 | * schedule the next one. |
1341 | * | 346 | * |
1342 | * If the peer is not the origin, do nothing. | 347 | * @param cls the `struct CadetConnection` to keep alive. |
1343 | * | 348 | * @param cid identifier of the connection within the tunnel, NULL |
1344 | * @param c Connection for which to schedule the next keepalive. | 349 | * if transmission failed |
1345 | * @param fwd Direction for the next keepalive. | ||
1346 | */ | 350 | */ |
1347 | static void | 351 | static void |
1348 | schedule_next_keepalive (struct CadetConnection *c, int fwd) | 352 | keepalive_done (void *cls, |
353 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
1349 | { | 354 | { |
1350 | struct GNUNET_TIME_Relative delay; | 355 | struct CadetConnection *cc = cls; |
1351 | struct GNUNET_SCHEDULER_Task * *task_id; | ||
1352 | GNUNET_SCHEDULER_TaskCallback keepalive_task; | ||
1353 | |||
1354 | GCC_check_connections (); | ||
1355 | if (GNUNET_NO == GCC_is_origin (c, fwd)) | ||
1356 | return; | ||
1357 | |||
1358 | /* Calculate delay to use, depending on the state of the connection */ | ||
1359 | if (CADET_CONNECTION_READY == c->state) | ||
1360 | { | ||
1361 | delay = refresh_connection_time; | ||
1362 | } | ||
1363 | else | ||
1364 | { | ||
1365 | if (1 > c->create_retry) | ||
1366 | c->create_retry = 1; | ||
1367 | delay = GNUNET_TIME_relative_saturating_multiply (create_connection_time, | ||
1368 | c->create_retry); | ||
1369 | if (c->create_retry < 64) // TODO make configurable | ||
1370 | c->create_retry *= 2; | ||
1371 | } | ||
1372 | |||
1373 | /* Select direction-dependent parameters */ | ||
1374 | if (GNUNET_YES == fwd) | ||
1375 | { | ||
1376 | task_id = &c->fwd_maintenance_task; | ||
1377 | keepalive_task = &connection_fwd_keepalive; | ||
1378 | } | ||
1379 | else | ||
1380 | { | ||
1381 | task_id = &c->bck_maintenance_task; | ||
1382 | keepalive_task = &connection_bck_keepalive; | ||
1383 | } | ||
1384 | 356 | ||
1385 | /* Check that no one scheduled it before us */ | 357 | cc->keepalive_qe = NULL; |
1386 | if (NULL != *task_id) | 358 | if ( (GNUNET_YES == cc->mqm_ready) && |
1387 | { | 359 | (NULL == cc->task) ) |
1388 | /* No need for a _break. It can happen for instance when sending a SYNACK | 360 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, |
1389 | * for a duplicate SYN: the first SYNACK scheduled the task. */ | 361 | &send_keepalive, |
1390 | GNUNET_SCHEDULER_cancel (*task_id); | 362 | cc); |
1391 | } | ||
1392 | |||
1393 | /* Schedule the task */ | ||
1394 | *task_id = GNUNET_SCHEDULER_add_delayed (delay, | ||
1395 | keepalive_task, | ||
1396 | c); | ||
1397 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1398 | "next keepalive for %s in in %s\n", | ||
1399 | GCC_2s (c), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); | ||
1400 | GCC_check_connections (); | ||
1401 | } | 363 | } |
1402 | 364 | ||
1403 | 365 | ||
1404 | /** | 366 | /** |
1405 | * Cancel all transmissions that belong to a certain connection. | 367 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the |
368 | * tunnel to prevent it from timing out. | ||
1406 | * | 369 | * |
1407 | * If the connection is scheduled for destruction and no more messages are left, | 370 | * @param cls the `struct CadetConnection` to keep alive. |
1408 | * the connection will be destroyed by the continuation call. | ||
1409 | * | ||
1410 | * @param c Connection which to cancel. Might be destroyed during this call. | ||
1411 | * @param fwd Cancel fwd traffic? | ||
1412 | */ | 371 | */ |
1413 | static void | 372 | static void |
1414 | connection_cancel_queues (struct CadetConnection *c, | 373 | send_keepalive (void *cls) |
1415 | int fwd) | ||
1416 | { | 374 | { |
1417 | struct CadetFlowControl *fc; | 375 | struct CadetConnection *cc = cls; |
376 | struct GNUNET_MessageHeader msg; | ||
1418 | 377 | ||
1419 | GCC_check_connections (); | 378 | cc->task = NULL; |
1420 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 379 | if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t)) |
1421 | "Cancel %s queues for connection %s\n", | ||
1422 | GC_f2s (fwd), GCC_2s (c)); | ||
1423 | if (NULL == c) | ||
1424 | { | 380 | { |
1425 | GNUNET_break (0); | 381 | /* Tunnel not yet ready, wait with keepalives... */ |
382 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
383 | &send_keepalive, | ||
384 | cc); | ||
1426 | return; | 385 | return; |
1427 | } | 386 | } |
1428 | 387 | GNUNET_assert (NULL != cc->ct); | |
1429 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | 388 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
1430 | if (NULL != fc->poll_task) | 389 | GNUNET_assert (NULL == cc->keepalive_qe); |
1431 | { | ||
1432 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
1433 | fc->poll_task = NULL; | ||
1434 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL task for fc %p\n", fc); | ||
1435 | } | ||
1436 | if (NULL != fc->poll_msg) | ||
1437 | { | ||
1438 | GCC_cancel (fc->poll_msg); | ||
1439 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL msg for fc %p\n", fc); | ||
1440 | } | ||
1441 | |||
1442 | while (NULL != fc->q_head) | ||
1443 | { | ||
1444 | GCC_cancel (fc->q_head); | ||
1445 | } | ||
1446 | GCC_check_connections (); | ||
1447 | } | ||
1448 | |||
1449 | |||
1450 | /** | ||
1451 | * Function called if a connection has been stalled for a while, | ||
1452 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1453 | * | ||
1454 | * @param cls Closure (poll ctx). | ||
1455 | */ | ||
1456 | static void | ||
1457 | send_poll (void *cls) | ||
1458 | { | ||
1459 | static struct CadetEncryptedMessageIdentifier zero; | ||
1460 | struct CadetFlowControl *fc = cls; | ||
1461 | struct GNUNET_CADET_ConnectionHopByHopPollMessage msg; | ||
1462 | struct CadetConnection *c; | ||
1463 | int fwd; | ||
1464 | |||
1465 | fc->poll_task = NULL; | ||
1466 | GCC_check_connections (); | ||
1467 | c = fc->c; | ||
1468 | fwd = fc == &c->fwd_fc; | ||
1469 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n", | ||
1470 | GCC_2s (c), GC_f2s (fwd)); | ||
1471 | |||
1472 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL); | ||
1473 | msg.header.size = htons (sizeof (msg)); | ||
1474 | msg.cid = c->id; | ||
1475 | msg.cemi = fc->last_pid_sent; | ||
1476 | LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid)); | ||
1477 | fc->poll_msg | ||
1478 | = GCC_send_prebuilt_message (&msg.header, | ||
1479 | UINT16_MAX, | ||
1480 | zero, | ||
1481 | c, | ||
1482 | fc == &c->fwd_fc, | ||
1483 | GNUNET_YES, | ||
1484 | NULL, | ||
1485 | NULL); | ||
1486 | GNUNET_assert (NULL != fc->poll_msg); | ||
1487 | GCC_check_connections (); | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | /** | ||
1492 | * Generic connection timeout implementation. | ||
1493 | * | ||
1494 | * Timeout function due to lack of keepalive/traffic from an endpoint. | ||
1495 | * Destroys connection if called. | ||
1496 | * | ||
1497 | * @param c Connection to destroy. | ||
1498 | * @param fwd Was the timeout from the origin? (FWD timeout) | ||
1499 | */ | ||
1500 | static void | ||
1501 | connection_timeout (struct CadetConnection *c, int fwd) | ||
1502 | { | ||
1503 | GCC_check_connections (); | ||
1504 | |||
1505 | LOG (GNUNET_ERROR_TYPE_INFO, | 390 | LOG (GNUNET_ERROR_TYPE_INFO, |
1506 | "Connection %s %s timed out. Destroying.\n", | 391 | "Sending KEEPALIVE on behalf of %s via %s\n", |
1507 | GCC_2s (c), | 392 | GCC_2s (cc), |
1508 | GC_f2s (fwd)); | 393 | GCT_2s (cc->ct->t)); |
1509 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | 394 | GNUNET_STATISTICS_update (stats, |
1510 | 395 | "# keepalives sent", | |
1511 | if (GCC_is_origin (c, fwd)) /* Loopback? Something is wrong! */ | 396 | 1, |
1512 | { | 397 | GNUNET_NO); |
1513 | GNUNET_break (0); | 398 | msg.size = htons (sizeof (msg)); |
1514 | return; | 399 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE); |
1515 | } | ||
1516 | |||
1517 | /* If dest, send "broken" notification. */ | ||
1518 | if (GCC_is_terminal (c, fwd)) | ||
1519 | { | ||
1520 | struct CadetPeer *next_hop; | ||
1521 | |||
1522 | next_hop = fwd ? get_prev_hop (c) : get_next_hop (c); | ||
1523 | send_broken_unknown (&c->id, &my_full_id, NULL, next_hop); | ||
1524 | } | ||
1525 | |||
1526 | GCC_destroy (c); | ||
1527 | GCC_check_connections (); | ||
1528 | } | ||
1529 | |||
1530 | |||
1531 | /** | ||
1532 | * Timeout function due to lack of keepalive/traffic from the owner. | ||
1533 | * Destroys connection if called. | ||
1534 | * | ||
1535 | * @param cls Closure (connection to destroy). | ||
1536 | */ | ||
1537 | static void | ||
1538 | connection_fwd_timeout (void *cls) | ||
1539 | { | ||
1540 | struct CadetConnection *c = cls; | ||
1541 | |||
1542 | c->fwd_maintenance_task = NULL; | ||
1543 | GCC_check_connections (); | ||
1544 | connection_timeout (c, GNUNET_YES); | ||
1545 | GCC_check_connections (); | ||
1546 | } | ||
1547 | |||
1548 | |||
1549 | /** | ||
1550 | * Timeout function due to lack of keepalive/traffic from the destination. | ||
1551 | * Destroys connection if called. | ||
1552 | * | ||
1553 | * @param cls Closure (connection to destroy). | ||
1554 | */ | ||
1555 | static void | ||
1556 | connection_bck_timeout (void *cls) | ||
1557 | { | ||
1558 | struct CadetConnection *c = cls; | ||
1559 | 400 | ||
1560 | c->bck_maintenance_task = NULL; | 401 | cc->keepalive_qe |
1561 | GCC_check_connections (); | 402 | = GCT_send (cc->ct->t, |
1562 | connection_timeout (c, GNUNET_NO); | 403 | &msg, |
1563 | GCC_check_connections (); | 404 | &keepalive_done, |
405 | cc); | ||
1564 | } | 406 | } |
1565 | 407 | ||
1566 | 408 | ||
1567 | /** | 409 | /** |
1568 | * Resets the connection timeout task, some other message has done the | 410 | * We sent a message for which we expect to receive an ACK via |
1569 | * task's job. | 411 | * the connection identified by @a cti. |
1570 | * - For the first peer on the direction this means to send | ||
1571 | * a keepalive or a path confirmation message (either create or ACK). | ||
1572 | * - For all other peers, this means to destroy the connection, | ||
1573 | * due to lack of activity. | ||
1574 | * Starts the timeout if no timeout was running (connection just created). | ||
1575 | * | ||
1576 | * @param c Connection whose timeout to reset. | ||
1577 | * @param fwd Is this forward? | ||
1578 | * | 412 | * |
1579 | * TODO use heap to improve efficiency of scheduler. | 413 | * @param cid connection identifier where we expect an ACK |
1580 | */ | 414 | */ |
1581 | static void | 415 | void |
1582 | connection_reset_timeout (struct CadetConnection *c, int fwd) | 416 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
1583 | { | 417 | { |
1584 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GC_f2s (fwd)); | 418 | struct CadetConnection *cc; |
1585 | if (GCC_is_origin (c, fwd)) /* Startpoint */ | ||
1586 | { | ||
1587 | schedule_next_keepalive (c, fwd); | ||
1588 | if (NULL != c->maintenance_q) | ||
1589 | { | ||
1590 | GCP_send_cancel (c->maintenance_q); | ||
1591 | c->maintenance_q = NULL; /* Is set to NULL by conn_message_sent anyway */ | ||
1592 | } | ||
1593 | } | ||
1594 | else /* Relay, endpoint. */ | ||
1595 | { | ||
1596 | struct GNUNET_TIME_Relative delay; | ||
1597 | struct GNUNET_SCHEDULER_Task * *ti; | ||
1598 | GNUNET_SCHEDULER_TaskCallback f; | ||
1599 | |||
1600 | ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task; | ||
1601 | 419 | ||
1602 | if (NULL != *ti) | 420 | cc = GCC_lookup (cid); |
1603 | GNUNET_SCHEDULER_cancel (*ti); | 421 | if (NULL == cc) |
1604 | delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 4); | 422 | return; /* whopise, connection alredy down? */ |
1605 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 423 | cc->metrics.num_acked_transmissions++; |
1606 | " timing out in %s\n", | ||
1607 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_NO)); | ||
1608 | f = fwd ? &connection_fwd_timeout : &connection_bck_timeout; | ||
1609 | *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c); | ||
1610 | } | ||
1611 | } | 424 | } |
1612 | 425 | ||
1613 | 426 | ||
1614 | /** | 427 | /** |
1615 | * Iterator to compare each connection's path with the path of a new connection. | 428 | * We observed an ACK for a message that was originally sent via |
429 | * the connection identified by @a cti. | ||
1616 | * | 430 | * |
1617 | * If the connection coincides, the c member of path is set to the connection | 431 | * @param cti connection identifier where we got an ACK for a message |
1618 | * and the destroy flag of the connection is set. | 432 | * that was originally sent via this connection (the ACK |
1619 | * | 433 | * may have gotten back to us via a different connection). |
1620 | * @param cls Closure (new path). | ||
1621 | * @param c Connection in the tunnel to check. | ||
1622 | */ | 434 | */ |
1623 | static void | 435 | void |
1624 | check_path (void *cls, struct CadetConnection *c) | 436 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
1625 | { | 437 | { |
1626 | struct CadetConnection *new_conn = cls; | 438 | struct CadetConnection *cc; |
1627 | struct CadetPeerPath *path = new_conn->path; | ||
1628 | |||
1629 | LOG (GNUNET_ERROR_TYPE_DEBUG, " checking %s (%p), length %u\n", | ||
1630 | GCC_2s (c), c, c->path->length); | ||
1631 | 439 | ||
1632 | if (c != new_conn | 440 | cc = GCC_lookup (cid); |
1633 | && GNUNET_NO == c->destroy | 441 | if (NULL == cc) |
1634 | && CADET_CONNECTION_BROKEN != c->state | 442 | return; /* whopise, connection alredy down? */ |
1635 | && CADET_CONNECTION_DESTROYED != c->state | 443 | cc->metrics.num_successes++; |
1636 | && path_equivalent (path, c->path)) | ||
1637 | { | ||
1638 | new_conn->destroy = GNUNET_YES; /* Do not mark_destroyed, */ | ||
1639 | new_conn->path->c = c; /* this is only a flag for the Iterator. */ | ||
1640 | LOG (GNUNET_ERROR_TYPE_DEBUG, " MATCH!\n"); | ||
1641 | } | ||
1642 | } | 444 | } |
1643 | 445 | ||
1644 | 446 | ||
1645 | /** | 447 | /** |
1646 | * Finds out if this path is already being used by an existing connection. | 448 | * We observed some the given @a latency on the connection |
1647 | * | 449 | * identified by @a cti. (The same connection was taken |
1648 | * Checks the tunnel towards the destination to see if it contains | 450 | * in both directions.) |
1649 | * any connection with the same path. | ||
1650 | * | 451 | * |
1651 | * If the existing connection is ready, it is kept. | 452 | * @param cid connection identifier where we measured latency |
1652 | * Otherwise if the sender has a smaller ID that ours, we accept it (and | 453 | * @param latency the observed latency |
1653 | * the peer will eventually reject our attempt). | ||
1654 | * | ||
1655 | * @param path Path to check. | ||
1656 | * @return #GNUNET_YES if the tunnel has a connection with the same path, | ||
1657 | * #GNUNET_NO otherwise. | ||
1658 | */ | 454 | */ |
1659 | static int | 455 | void |
1660 | does_connection_exist (struct CadetConnection *conn) | 456 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
457 | struct GNUNET_TIME_Relative latency) | ||
1661 | { | 458 | { |
1662 | struct CadetPeer *p; | 459 | struct CadetConnection *cc; |
1663 | struct CadetTunnel *t; | 460 | double weight; |
1664 | struct CadetConnection *c; | 461 | double result; |
1665 | |||
1666 | p = GCP_get_short (conn->path->peers[0], GNUNET_NO); | ||
1667 | if (NULL == p) | ||
1668 | return GNUNET_NO; | ||
1669 | t = GCP_get_tunnel (p); | ||
1670 | if (NULL == t) | ||
1671 | return GNUNET_NO; | ||
1672 | |||
1673 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking for duplicates\n"); | ||
1674 | 462 | ||
1675 | GCT_iterate_connections (t, &check_path, conn); | 463 | cc = GCC_lookup (cid); |
1676 | 464 | if (NULL == cc) | |
1677 | if (GNUNET_YES == conn->destroy) | 465 | return; /* whopise, connection alredy down? */ |
1678 | { | 466 | GNUNET_STATISTICS_update (stats, |
1679 | c = conn->path->c; | 467 | "# latencies observed", |
1680 | conn->destroy = GNUNET_NO; | 468 | 1, |
1681 | conn->path->c = conn; | 469 | GNUNET_NO); |
1682 | LOG (GNUNET_ERROR_TYPE_DEBUG, " found duplicate of %s\n", GCC_2s (conn)); | 470 | cc->latency_datapoints++; |
1683 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate: %s\n", GCC_2s (c)); | 471 | if (cc->latency_datapoints >= 7) |
1684 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | 472 | weight = 7.0; |
1685 | if (CADET_CONNECTION_READY == c->state) | ||
1686 | { | ||
1687 | /* The other peer confirmed a live connection with this path, | ||
1688 | * why are they trying to duplicate it? */ | ||
1689 | GNUNET_STATISTICS_update (stats, "# duplicate connections", 1, GNUNET_NO); | ||
1690 | return GNUNET_YES; | ||
1691 | } | ||
1692 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate not ready, connection unique\n"); | ||
1693 | return GNUNET_NO; | ||
1694 | } | ||
1695 | else | 473 | else |
1696 | { | 474 | weight = cc->latency_datapoints; |
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s has no duplicates\n", GCC_2s (conn)); | 475 | /* Compute weighted average, giving at MOST weight 7 to the |
1698 | return GNUNET_NO; | 476 | existing values, or less if that value is based on fewer than 7 |
1699 | } | 477 | measurements. */ |
478 | result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us; | ||
479 | result /= (weight + 1.0); | ||
480 | cc->metrics.aged_latency.rel_value_us = (uint64_t) result; | ||
1700 | } | 481 | } |
1701 | 482 | ||
1702 | 483 | ||
1703 | /** | 484 | /** |
1704 | * @brief Check if the tunnel this connection belongs to has any other | 485 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying |
1705 | * connection with the same path, and destroy one if so. | 486 | * that the end-to-end connection is up. Process it. |
1706 | * | 487 | * |
1707 | * @param cls Closure (connection to check). | 488 | * @param cc the connection that got the ACK. |
1708 | */ | ||
1709 | static void | ||
1710 | check_duplicates (void *cls) | ||
1711 | { | ||
1712 | struct CadetConnection *c = cls; | ||
1713 | |||
1714 | c->check_duplicates_task = NULL; | ||
1715 | if (GNUNET_YES == does_connection_exist (c)) | ||
1716 | { | ||
1717 | GCT_debug (c->t, GNUNET_ERROR_TYPE_DEBUG); | ||
1718 | send_broken (c, &my_full_id, &my_full_id, GCC_is_origin (c, GNUNET_YES)); | ||
1719 | GCC_destroy (c); | ||
1720 | } | ||
1721 | } | ||
1722 | |||
1723 | |||
1724 | /** | ||
1725 | * Wait for enough time to let any dead connections time out and check for | ||
1726 | * any remaining duplicates. | ||
1727 | * | ||
1728 | * @param c Connection that is a potential duplicate. | ||
1729 | */ | ||
1730 | static void | ||
1731 | schedule_check_duplicates (struct CadetConnection *c) | ||
1732 | { | ||
1733 | struct GNUNET_TIME_Relative delay; | ||
1734 | |||
1735 | if (NULL != c->check_duplicates_task) | ||
1736 | return; | ||
1737 | delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 5); | ||
1738 | c->check_duplicates_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
1739 | &check_duplicates, | ||
1740 | c); | ||
1741 | } | ||
1742 | |||
1743 | |||
1744 | /** | ||
1745 | * Add the connection to the list of both neighbors. | ||
1746 | * | ||
1747 | * @param c Connection. | ||
1748 | * | ||
1749 | * @return #GNUNET_OK if everything went fine | ||
1750 | * #GNUNET_SYSERR if the was an error and @c c is malformed. | ||
1751 | */ | ||
1752 | static int | ||
1753 | register_neighbors (struct CadetConnection *c) | ||
1754 | { | ||
1755 | c->next_peer = get_next_hop (c); | ||
1756 | c->prev_peer = get_prev_hop (c); | ||
1757 | GNUNET_assert (c->next_peer != c->prev_peer); | ||
1758 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1759 | "register neighbors for connection %s\n", | ||
1760 | GCC_2s (c)); | ||
1761 | path_debug (c->path); | ||
1762 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1763 | "own pos %u\n", c->own_pos); | ||
1764 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1765 | "putting connection %s to next peer %p\n", | ||
1766 | GCC_2s (c), | ||
1767 | c->next_peer); | ||
1768 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", | ||
1769 | c->next_peer, | ||
1770 | GCP_2s (c->next_peer)); | ||
1771 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1772 | "putting connection %s to prev peer %p\n", | ||
1773 | GCC_2s (c), | ||
1774 | c->prev_peer); | ||
1775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1776 | "prev peer %p %s\n", | ||
1777 | c->prev_peer, | ||
1778 | GCP_2s (c->prev_peer)); | ||
1779 | |||
1780 | if ( (GNUNET_NO == GCP_is_neighbor (c->next_peer)) || | ||
1781 | (GNUNET_NO == GCP_is_neighbor (c->prev_peer)) ) | ||
1782 | { | ||
1783 | if (GCC_is_origin (c, GNUNET_YES)) | ||
1784 | GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO); | ||
1785 | GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO); | ||
1786 | |||
1787 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1788 | " register neighbors failed\n"); | ||
1789 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1790 | " prev: %s, neighbor?: %d\n", | ||
1791 | GCP_2s (c->prev_peer), | ||
1792 | GCP_is_neighbor (c->prev_peer)); | ||
1793 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1794 | " next: %s, neighbor?: %d\n", | ||
1795 | GCP_2s (c->next_peer), | ||
1796 | GCP_is_neighbor (c->next_peer)); | ||
1797 | return GNUNET_SYSERR; | ||
1798 | } | ||
1799 | GCP_add_connection (c->next_peer, c, GNUNET_NO); | ||
1800 | GCP_add_connection (c->prev_peer, c, GNUNET_YES); | ||
1801 | |||
1802 | return GNUNET_OK; | ||
1803 | } | ||
1804 | |||
1805 | |||
1806 | /** | ||
1807 | * Remove the connection from the list of both neighbors. | ||
1808 | * | ||
1809 | * @param c Connection. | ||
1810 | */ | ||
1811 | static void | ||
1812 | unregister_neighbors (struct CadetConnection *c) | ||
1813 | { | ||
1814 | // struct CadetPeer *peer; FIXME dont use next_peer, prev_peer | ||
1815 | /* Either already unregistered or never got registered, it's ok either way. */ | ||
1816 | if (NULL == c->path) | ||
1817 | return; | ||
1818 | if (NULL != c->next_peer) | ||
1819 | { | ||
1820 | GCP_remove_connection (c->next_peer, c); | ||
1821 | c->next_peer = NULL; | ||
1822 | } | ||
1823 | if (NULL != c->prev_peer) | ||
1824 | { | ||
1825 | GCP_remove_connection (c->prev_peer, c); | ||
1826 | c->prev_peer = NULL; | ||
1827 | } | ||
1828 | } | ||
1829 | |||
1830 | |||
1831 | /** | ||
1832 | * Invalidates all paths towards all peers that comprise the connection which | ||
1833 | * rely on the disconnected peer. | ||
1834 | * | ||
1835 | * ~O(n^3) (peers in connection * paths/peer * links/path) | ||
1836 | * | ||
1837 | * @param c Connection whose peers' paths to clean. | ||
1838 | * @param disconnected Peer that disconnected. | ||
1839 | */ | ||
1840 | static void | ||
1841 | invalidate_paths (struct CadetConnection *c, | ||
1842 | struct CadetPeer *disconnected) | ||
1843 | { | ||
1844 | struct CadetPeer *peer; | ||
1845 | unsigned int i; | ||
1846 | |||
1847 | for (i = 0; i < c->path->length; i++) | ||
1848 | { | ||
1849 | peer = GCP_get_short (c->path->peers[i], GNUNET_NO); | ||
1850 | if (NULL != peer) | ||
1851 | GCP_notify_broken_link (peer, &my_full_id, GCP_get_id (disconnected)); | ||
1852 | } | ||
1853 | } | ||
1854 | |||
1855 | |||
1856 | /** | ||
1857 | * Bind the connection to the peer and the tunnel to that peer. | ||
1858 | * | ||
1859 | * If the peer has no tunnel, create one. Update tunnel and connection | ||
1860 | * data structres to reflect new status. | ||
1861 | * | ||
1862 | * @param c Connection. | ||
1863 | * @param peer Peer. | ||
1864 | */ | ||
1865 | static void | ||
1866 | add_to_peer (struct CadetConnection *c, | ||
1867 | struct CadetPeer *peer) | ||
1868 | { | ||
1869 | GCP_add_tunnel (peer); | ||
1870 | c->t = GCP_get_tunnel (peer); | ||
1871 | GCT_add_connection (c->t, c); | ||
1872 | } | ||
1873 | |||
1874 | |||
1875 | /** | ||
1876 | * Log receipt of message on stderr (INFO level). | ||
1877 | * | ||
1878 | * @param message Message received. | ||
1879 | * @param peer Peer who sent the message. | ||
1880 | * @param conn_id Connection ID of the message. | ||
1881 | */ | ||
1882 | static void | ||
1883 | log_message (const struct GNUNET_MessageHeader *message, | ||
1884 | const struct CadetPeer *peer, | ||
1885 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id) | ||
1886 | { | ||
1887 | uint16_t size; | ||
1888 | uint16_t type; | ||
1889 | char *arrow; | ||
1890 | |||
1891 | size = ntohs (message->size); | ||
1892 | type = ntohs (message->type); | ||
1893 | switch (type) | ||
1894 | { | ||
1895 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1896 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
1897 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1898 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1899 | arrow = "=="; | ||
1900 | break; | ||
1901 | default: | ||
1902 | arrow = "--"; | ||
1903 | } | ||
1904 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1905 | "<%s %s on conn %s from %s, %6u bytes\n", | ||
1906 | arrow, | ||
1907 | GC_m2s (type), | ||
1908 | GNUNET_sh2s (&conn_id->connection_of_tunnel), | ||
1909 | GCP_2s(peer), | ||
1910 | (unsigned int) size); | ||
1911 | } | ||
1912 | |||
1913 | /******************************************************************************/ | ||
1914 | /******************************** API ***********************************/ | ||
1915 | /******************************************************************************/ | ||
1916 | |||
1917 | /** | ||
1918 | * Handler for connection creation. | ||
1919 | * | ||
1920 | * @param peer Message sender (neighbor). | ||
1921 | * @param msg Message itself. | ||
1922 | */ | 489 | */ |
1923 | void | 490 | void |
1924 | GCC_handle_create (struct CadetPeer *peer, | 491 | GCC_handle_connection_create_ack (struct CadetConnection *cc) |
1925 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
1926 | { | 492 | { |
1927 | static struct CadetEncryptedMessageIdentifier zero; | 493 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1928 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid; | 494 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", |
1929 | struct GNUNET_PeerIdentity *id; | 495 | GCC_2s (cc), |
1930 | struct CadetPeerPath *path; | 496 | cc->state, |
1931 | struct CadetPeer *dest_peer; | 497 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); |
1932 | struct CadetPeer *orig_peer; | 498 | if (CADET_CONNECTION_READY == cc->state) |
1933 | struct CadetConnection *c; | 499 | return; /* Duplicate ACK, ignore */ |
1934 | unsigned int own_pos; | 500 | if (NULL != cc->task) |
1935 | uint16_t size; | ||
1936 | |||
1937 | GCC_check_connections (); | ||
1938 | size = ntohs (msg->header.size); | ||
1939 | |||
1940 | /* Calculate hops */ | ||
1941 | size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage); | ||
1942 | if (0 != size % sizeof (struct GNUNET_PeerIdentity)) | ||
1943 | { | ||
1944 | GNUNET_break_op (0); | ||
1945 | return; | ||
1946 | } | ||
1947 | size /= sizeof (struct GNUNET_PeerIdentity); | ||
1948 | if (1 > size) | ||
1949 | { | ||
1950 | GNUNET_break_op (0); | ||
1951 | return; | ||
1952 | } | ||
1953 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); | ||
1954 | |||
1955 | /* Get parameters */ | ||
1956 | cid = &msg->cid; | ||
1957 | log_message (&msg->header, peer, cid); | ||
1958 | id = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1959 | LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id)); | ||
1960 | |||
1961 | /* Create connection */ | ||
1962 | c = connection_get (cid); | ||
1963 | if (NULL == c) | ||
1964 | { | ||
1965 | path = path_build_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1], | ||
1966 | size, myid, &own_pos); | ||
1967 | if (NULL == path) | ||
1968 | { | ||
1969 | /* Path was malformed, probably our own ID was not in it. */ | ||
1970 | GNUNET_STATISTICS_update (stats, "# malformed paths", 1, GNUNET_NO); | ||
1971 | GNUNET_break_op (0); | ||
1972 | return; | ||
1973 | } | ||
1974 | if (0 == own_pos) | ||
1975 | { | ||
1976 | /* We received this request from a neighbor, we cannot be origin */ | ||
1977 | GNUNET_STATISTICS_update (stats, "# fake paths", 1, GNUNET_NO); | ||
1978 | GNUNET_break_op (0); | ||
1979 | path_destroy (path); | ||
1980 | return; | ||
1981 | } | ||
1982 | |||
1983 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); | ||
1984 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); | ||
1985 | c = GCC_new (cid, NULL, path, own_pos); | ||
1986 | if (NULL == c) | ||
1987 | { | ||
1988 | if (path->length - 1 == own_pos) | ||
1989 | { | ||
1990 | /* If we are destination, why did the creation fail? */ | ||
1991 | GNUNET_break (0); | ||
1992 | path_destroy (path); | ||
1993 | GCC_check_connections (); | ||
1994 | return; | ||
1995 | } | ||
1996 | send_broken_unknown (cid, &my_full_id, | ||
1997 | GNUNET_PEER_resolve2 (path->peers[own_pos + 1]), | ||
1998 | peer); | ||
1999 | path_destroy (path); | ||
2000 | GCC_check_connections (); | ||
2001 | return; | ||
2002 | } | ||
2003 | GCP_add_path_to_all (path, GNUNET_NO); | ||
2004 | connection_reset_timeout (c, GNUNET_YES); | ||
2005 | } | ||
2006 | else | ||
2007 | { | ||
2008 | path = path_duplicate (c->path); | ||
2009 | } | ||
2010 | if (CADET_CONNECTION_NEW == c->state) | ||
2011 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
2012 | |||
2013 | /* Remember peers */ | ||
2014 | dest_peer = GCP_get (&id[size - 1], GNUNET_YES); | ||
2015 | orig_peer = GCP_get (&id[0], GNUNET_YES); | ||
2016 | |||
2017 | /* Is it a connection to us? */ | ||
2018 | if (c->own_pos == path->length - 1) | ||
2019 | { | ||
2020 | LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); | ||
2021 | GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); | ||
2022 | |||
2023 | add_to_peer (c, orig_peer); | ||
2024 | if (GNUNET_YES == does_connection_exist (c)) | ||
2025 | { | ||
2026 | /* Peer created a connection equal to one we think exists | ||
2027 | * and is fine. | ||
2028 | * Solution: Keep both and postpone disambiguation. In the meantime | ||
2029 | * the connection will time out or peer will inform us it is broken. | ||
2030 | * | ||
2031 | * Other options: | ||
2032 | * - Use explicit duplicate. | ||
2033 | * - Accept new conn and destroy the old. (interruption in higher level) | ||
2034 | * - Keep the one with higher ID / created by peer with higher ID. */ | ||
2035 | schedule_check_duplicates (c); | ||
2036 | } | ||
2037 | |||
2038 | if (CADET_TUNNEL_NEW == GCT_get_cstate (c->t)) | ||
2039 | GCT_change_cstate (c->t, CADET_TUNNEL_WAITING); | ||
2040 | if (NULL == c->maintenance_q) | ||
2041 | send_connection_ack (c, GNUNET_NO); | ||
2042 | if (CADET_CONNECTION_SENT == c->state) | ||
2043 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
2044 | } | ||
2045 | else | ||
2046 | { | 501 | { |
2047 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | 502 | GNUNET_SCHEDULER_cancel (cc->task); |
2048 | GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); | 503 | cc->task = NULL; |
2049 | GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); | ||
2050 | (void) GCC_send_prebuilt_message (&msg->header, | ||
2051 | 0, | ||
2052 | zero, | ||
2053 | c, | ||
2054 | GNUNET_YES, GNUNET_YES, | ||
2055 | NULL, NULL); | ||
2056 | } | 504 | } |
2057 | path_destroy (path); | 505 | cc->metrics.age = GNUNET_TIME_absolute_get (); |
2058 | GCC_check_connections (); | 506 | update_state (cc, |
507 | CADET_CONNECTION_READY, | ||
508 | cc->mqm_ready); | ||
509 | if ( (NULL == cc->keepalive_qe) && | ||
510 | (GNUNET_YES == cc->mqm_ready) && | ||
511 | (NULL == cc->task) ) | ||
512 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
513 | &send_keepalive, | ||
514 | cc); | ||
2059 | } | 515 | } |
2060 | 516 | ||
2061 | 517 | ||
2062 | /** | 518 | /** |
2063 | * Handler for connection confirmations. | 519 | * Handle KX message. |
2064 | * | 520 | * |
2065 | * @param peer Message sender (neighbor). | 521 | * @param cc connection that received encrypted message |
2066 | * @param msg Message itself. | 522 | * @param msg the key exchange message |
2067 | */ | 523 | */ |
2068 | void | 524 | void |
2069 | GCC_handle_confirm (struct CadetPeer *peer, | 525 | GCC_handle_kx (struct CadetConnection *cc, |
2070 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | 526 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
2071 | { | 527 | { |
2072 | static struct CadetEncryptedMessageIdentifier zero; | 528 | if (CADET_CONNECTION_SENT == cc->state) |
2073 | struct CadetConnection *c; | ||
2074 | enum CadetConnectionState oldstate; | ||
2075 | int fwd; | ||
2076 | |||
2077 | GCC_check_connections (); | ||
2078 | log_message (&msg->header, peer, &msg->cid); | ||
2079 | c = connection_get (&msg->cid); | ||
2080 | if (NULL == c) | ||
2081 | { | ||
2082 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
2083 | 1, GNUNET_NO); | ||
2084 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2085 | " don't know the connection!\n"); | ||
2086 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2087 | GCC_check_connections (); | ||
2088 | return; | ||
2089 | } | ||
2090 | if (GNUNET_NO != c->destroy) | ||
2091 | { | 529 | { |
2092 | GNUNET_assert (CADET_CONNECTION_DESTROYED == c->state); | 530 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
2093 | GNUNET_STATISTICS_update (stats, "# control on dying connection", | 531 | clearly something is working, so pretend we got an ACK. */ |
2094 | 1, GNUNET_NO); | ||
2095 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 532 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2096 | "connection %s being destroyed, ignoring confirm\n", | 533 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", |
2097 | GCC_2s (c)); | 534 | GCC_2s (cc)); |
2098 | GCC_check_connections (); | 535 | GCC_handle_connection_create_ack (cc); |
2099 | return; | ||
2100 | } | ||
2101 | |||
2102 | oldstate = c->state; | ||
2103 | LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GCP_2s (peer)); | ||
2104 | if (get_next_hop (c) == peer) | ||
2105 | { | ||
2106 | LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); | ||
2107 | fwd = GNUNET_NO; | ||
2108 | if (CADET_CONNECTION_SENT == oldstate) | ||
2109 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
2110 | } | ||
2111 | else if (get_prev_hop (c) == peer) | ||
2112 | { | ||
2113 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FINAL ACK\n"); | ||
2114 | fwd = GNUNET_YES; | ||
2115 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2116 | } | ||
2117 | else | ||
2118 | { | ||
2119 | GNUNET_STATISTICS_update (stats, "# control on connection from wrong peer", | ||
2120 | 1, GNUNET_NO); | ||
2121 | GNUNET_break_op (0); | ||
2122 | return; | ||
2123 | } | ||
2124 | |||
2125 | connection_reset_timeout (c, fwd); | ||
2126 | |||
2127 | GNUNET_assert (NULL != c->path); | ||
2128 | GCP_add_path_to_all (c->path, GNUNET_YES); | ||
2129 | |||
2130 | /* Message for us as creator? */ | ||
2131 | if (GNUNET_YES == GCC_is_origin (c, GNUNET_YES)) | ||
2132 | { | ||
2133 | if (GNUNET_NO != fwd) | ||
2134 | { | ||
2135 | GNUNET_break (0); | ||
2136 | return; | ||
2137 | } | ||
2138 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); | ||
2139 | |||
2140 | /* If just created, cancel the short timeout and start a long one */ | ||
2141 | if (CADET_CONNECTION_SENT == oldstate) | ||
2142 | { | ||
2143 | c->create_retry = 1; | ||
2144 | connection_reset_timeout (c, GNUNET_YES); | ||
2145 | } | ||
2146 | |||
2147 | /* Change connection state, send ACK */ | ||
2148 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2149 | send_connection_ack (c, GNUNET_YES); | ||
2150 | |||
2151 | /* Change tunnel state, trigger KX */ | ||
2152 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2153 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2154 | GCC_check_connections (); | ||
2155 | return; | ||
2156 | } | ||
2157 | |||
2158 | /* Message for us as destination? */ | ||
2159 | if (GCC_is_terminal (c, GNUNET_YES)) | ||
2160 | { | ||
2161 | if (GNUNET_YES != fwd) | ||
2162 | { | ||
2163 | GNUNET_break (0); | ||
2164 | return; | ||
2165 | } | ||
2166 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); | ||
2167 | |||
2168 | /* If just created, cancel the short timeout and start a long one */ | ||
2169 | if (CADET_CONNECTION_ACK == oldstate) | ||
2170 | connection_reset_timeout (c, GNUNET_NO); | ||
2171 | |||
2172 | /* Change tunnel state */ | ||
2173 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2174 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2175 | GCC_check_connections (); | ||
2176 | } | 536 | } |
2177 | else | 537 | GCT_handle_kx (cc->ct, |
2178 | { | 538 | msg); |
2179 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2180 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2181 | zero, | ||
2182 | c, | ||
2183 | fwd, | ||
2184 | GNUNET_YES, NULL, NULL); | ||
2185 | } | ||
2186 | GCC_check_connections (); | ||
2187 | } | 539 | } |
2188 | 540 | ||
2189 | 541 | ||
2190 | /** | 542 | /** |
2191 | * Handler for notifications of broken connections. | 543 | * Handle KX_AUTH message. |
2192 | * | 544 | * |
2193 | * @param peer Message sender (neighbor). | 545 | * @param cc connection that received encrypted message |
2194 | * @param msg Message itself. | 546 | * @param msg the key exchange message |
2195 | */ | 547 | */ |
2196 | void | 548 | void |
2197 | GCC_handle_broken (struct CadetPeer *peer, | 549 | GCC_handle_kx_auth (struct CadetConnection *cc, |
2198 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | 550 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) |
2199 | { | 551 | { |
2200 | static struct CadetEncryptedMessageIdentifier zero; | 552 | if (CADET_CONNECTION_SENT == cc->state) |
2201 | struct CadetConnection *c; | ||
2202 | struct CadetTunnel *t; | ||
2203 | int fwd; | ||
2204 | |||
2205 | GCC_check_connections (); | ||
2206 | log_message (&msg->header, peer, &msg->cid); | ||
2207 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer1)); | ||
2208 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer2)); | ||
2209 | c = connection_get (&msg->cid); | ||
2210 | if (NULL == c) | ||
2211 | { | ||
2212 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n"); | ||
2213 | GNUNET_STATISTICS_update (stats, "# duplicate CONNECTION_BROKEN", | ||
2214 | 1, GNUNET_NO); | ||
2215 | GCC_check_connections (); | ||
2216 | return; | ||
2217 | } | ||
2218 | |||
2219 | t = c->t; | ||
2220 | |||
2221 | fwd = is_fwd (c, peer); | ||
2222 | if (GNUNET_SYSERR == fwd) | ||
2223 | { | ||
2224 | GNUNET_break_op (0); | ||
2225 | GCC_check_connections (); | ||
2226 | return; | ||
2227 | } | ||
2228 | mark_destroyed (c); | ||
2229 | if (GCC_is_terminal (c, fwd)) | ||
2230 | { | ||
2231 | struct CadetPeer *endpoint; | ||
2232 | |||
2233 | if (NULL == t) | ||
2234 | { | ||
2235 | /* A terminal connection should not have 't' set to NULL. */ | ||
2236 | GNUNET_break (0); | ||
2237 | GCC_debug (c, GNUNET_ERROR_TYPE_ERROR); | ||
2238 | return; | ||
2239 | } | ||
2240 | endpoint = GCP_get_short (c->path->peers[c->path->length - 1], GNUNET_YES); | ||
2241 | if (2 < c->path->length) | ||
2242 | path_invalidate (c->path); | ||
2243 | GCP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); | ||
2244 | |||
2245 | connection_change_state (c, CADET_CONNECTION_BROKEN); | ||
2246 | GCT_remove_connection (t, c); | ||
2247 | c->t = NULL; | ||
2248 | |||
2249 | GCC_destroy (c); | ||
2250 | } | ||
2251 | else | ||
2252 | { | 553 | { |
2253 | (void) GCC_send_prebuilt_message (&msg->header, 0, | 554 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
2254 | zero, c, fwd, | 555 | clearly something is working, so pretend we got an ACK. */ |
2255 | GNUNET_YES, NULL, NULL); | 556 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2256 | connection_cancel_queues (c, !fwd); | 557 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", |
558 | GCC_2s (cc)); | ||
559 | GCC_handle_connection_create_ack (cc); | ||
2257 | } | 560 | } |
2258 | GCC_check_connections (); | 561 | GCT_handle_kx_auth (cc->ct, |
2259 | return; | 562 | msg); |
2260 | } | 563 | } |
2261 | 564 | ||
2262 | 565 | ||
2263 | /** | 566 | /** |
2264 | * Handler for notifications of destroyed connections. | 567 | * Handle encrypted message. |
2265 | * | 568 | * |
2266 | * @param peer Message sender (neighbor). | 569 | * @param cc connection that received encrypted message |
2267 | * @param msg Message itself. | 570 | * @param msg the encrypted message to decrypt |
2268 | */ | 571 | */ |
2269 | void | 572 | void |
2270 | GCC_handle_destroy (struct CadetPeer *peer, | 573 | GCC_handle_encrypted (struct CadetConnection *cc, |
2271 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | 574 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) |
2272 | { | 575 | { |
2273 | static struct CadetEncryptedMessageIdentifier zero; | 576 | if (CADET_CONNECTION_SENT == cc->state) |
2274 | struct CadetConnection *c; | ||
2275 | int fwd; | ||
2276 | |||
2277 | GCC_check_connections (); | ||
2278 | log_message (&msg->header, peer, &msg->cid); | ||
2279 | c = connection_get (&msg->cid); | ||
2280 | if (NULL == c) | ||
2281 | { | 577 | { |
2282 | /* Probably already got the message from another path, | 578 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, |
2283 | * destroyed the tunnel and retransmitted to children. | 579 | clearly something is working, so pretend we got an ACK. */ |
2284 | * Safe to ignore. | ||
2285 | */ | ||
2286 | GNUNET_STATISTICS_update (stats, | ||
2287 | "# control on unknown connection", | ||
2288 | 1, GNUNET_NO); | ||
2289 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 580 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2290 | " connection unknown destroyed: previously destroyed?\n"); | 581 | "Faking connection ACK for %s due to ENCRYPTED payload\n", |
2291 | GCC_check_connections (); | 582 | GCC_2s (cc)); |
2292 | return; | 583 | GCC_handle_connection_create_ack (cc); |
2293 | } | ||
2294 | |||
2295 | fwd = is_fwd (c, peer); | ||
2296 | if (GNUNET_SYSERR == fwd) | ||
2297 | { | ||
2298 | GNUNET_break_op (0); | ||
2299 | GCC_check_connections (); | ||
2300 | return; | ||
2301 | } | ||
2302 | |||
2303 | if (GNUNET_NO == GCC_is_terminal (c, fwd)) | ||
2304 | { | ||
2305 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2306 | zero, c, fwd, | ||
2307 | GNUNET_YES, NULL, NULL); | ||
2308 | } | 584 | } |
2309 | else if (0 == c->pending_messages) | 585 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); |
2310 | { | 586 | GCT_handle_encrypted (cc->ct, |
2311 | LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); | 587 | msg); |
2312 | GCC_destroy (c); | ||
2313 | GCC_check_connections (); | ||
2314 | return; | ||
2315 | } | ||
2316 | mark_destroyed (c); | ||
2317 | if (NULL != c->t) | ||
2318 | { | ||
2319 | GCT_remove_connection (c->t, c); | ||
2320 | c->t = NULL; | ||
2321 | } | ||
2322 | GCC_check_connections (); | ||
2323 | return; | ||
2324 | } | 588 | } |
2325 | 589 | ||
2326 | 590 | ||
2327 | /** | 591 | /** |
2328 | * Handler for cadet network traffic hop-by-hop acks. | 592 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the |
593 | * first hop. | ||
2329 | * | 594 | * |
2330 | * @param peer Message sender (neighbor). | 595 | * @param cls the `struct CadetConnection` to initiate |
2331 | * @param msg Message itself. | ||
2332 | */ | 596 | */ |
2333 | void | 597 | static void |
2334 | GCC_handle_ack (struct CadetPeer *peer, | 598 | send_create (void *cls) |
2335 | const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) | 599 | { |
2336 | { | 600 | struct CadetConnection *cc = cls; |
2337 | struct CadetConnection *c; | 601 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; |
2338 | struct CadetFlowControl *fc; | 602 | struct GNUNET_PeerIdentity *pids; |
2339 | struct CadetEncryptedMessageIdentifier ack; | 603 | struct GNUNET_MQ_Envelope *env; |
2340 | int fwd; | 604 | unsigned int path_length; |
2341 | 605 | ||
2342 | GCC_check_connections (); | 606 | cc->task = NULL; |
2343 | log_message (&msg->header, peer, &msg->cid); | 607 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
2344 | c = connection_get (&msg->cid); | 608 | path_length = GCPP_get_length (cc->path); |
2345 | if (NULL == c) | 609 | env = GNUNET_MQ_msg_extra (create_msg, |
2346 | { | 610 | (1 + path_length) * sizeof (struct GNUNET_PeerIdentity), |
2347 | GNUNET_STATISTICS_update (stats, | 611 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); |
2348 | "# ack on unknown connection", | 612 | create_msg->options = htonl ((uint32_t) cc->options); |
2349 | 1, | 613 | create_msg->cid = cc->cid; |
2350 | GNUNET_NO); | 614 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; |
2351 | send_broken_unknown (&msg->cid, | 615 | pids[0] = my_full_id; |
2352 | &my_full_id, | 616 | for (unsigned int i=0;i<path_length;i++) |
2353 | NULL, | 617 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, |
2354 | peer); | 618 | i)); |
2355 | GCC_check_connections (); | 619 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2356 | return; | 620 | "Sending CADET_CONNECTION_CREATE message for %s\n", |
2357 | } | 621 | GCC_2s (cc)); |
2358 | 622 | cc->env = env; | |
2359 | /* Is this a forward or backward ACK? */ | 623 | update_state (cc, |
2360 | if (get_next_hop (c) == peer) | 624 | CADET_CONNECTION_SENT, |
2361 | { | 625 | GNUNET_NO); |
2362 | fc = &c->fwd_fc; | 626 | GCP_send (cc->mq_man, |
2363 | fwd = GNUNET_YES; | 627 | env); |
2364 | } | ||
2365 | else if (get_prev_hop (c) == peer) | ||
2366 | { | ||
2367 | fc = &c->bck_fc; | ||
2368 | fwd = GNUNET_NO; | ||
2369 | } | ||
2370 | else | ||
2371 | { | ||
2372 | GNUNET_break_op (0); | ||
2373 | return; | ||
2374 | } | ||
2375 | |||
2376 | ack = msg->cemi_max; | ||
2377 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n", | ||
2378 | GC_f2s (fwd), | ||
2379 | ntohl (ack.pid), | ||
2380 | ntohl (fc->last_ack_recv.pid)); | ||
2381 | if (GC_is_pid_bigger (ntohl (ack.pid), | ||
2382 | ntohl (fc->last_ack_recv.pid))) | ||
2383 | fc->last_ack_recv = ack; | ||
2384 | |||
2385 | /* Cancel polling if the ACK is big enough. */ | ||
2386 | if ( (NULL != fc->poll_task) & | ||
2387 | GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid), | ||
2388 | ntohl (fc->last_pid_sent.pid))) | ||
2389 | { | ||
2390 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); | ||
2391 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
2392 | fc->poll_task = NULL; | ||
2393 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
2394 | } | ||
2395 | |||
2396 | GCC_check_connections (); | ||
2397 | } | 628 | } |
2398 | 629 | ||
2399 | 630 | ||
2400 | /** | 631 | /** |
2401 | * Handler for cadet network traffic hop-by-hop data counter polls. | 632 | * Send a CREATE_ACK message towards the origin. |
2402 | * | 633 | * |
2403 | * @param peer Message sender (neighbor). | 634 | * @param cls the `struct CadetConnection` to initiate |
2404 | * @param msg Message itself. | ||
2405 | */ | 635 | */ |
2406 | void | 636 | static void |
2407 | GCC_handle_poll (struct CadetPeer *peer, | 637 | send_create_ack (void *cls) |
2408 | const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg) | ||
2409 | { | 638 | { |
2410 | struct CadetConnection *c; | 639 | struct CadetConnection *cc = cls; |
2411 | struct CadetFlowControl *fc; | 640 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; |
2412 | struct CadetEncryptedMessageIdentifier pid; | 641 | struct GNUNET_MQ_Envelope *env; |
2413 | int fwd; | ||
2414 | |||
2415 | GCC_check_connections (); | ||
2416 | log_message (&msg->header, peer, &msg->cid); | ||
2417 | c = connection_get (&msg->cid); | ||
2418 | if (NULL == c) | ||
2419 | { | ||
2420 | GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, | ||
2421 | GNUNET_NO); | ||
2422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2423 | "POLL message on unknown connection %s!\n", | ||
2424 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
2425 | send_broken_unknown (&msg->cid, | ||
2426 | &my_full_id, | ||
2427 | NULL, | ||
2428 | peer); | ||
2429 | GCC_check_connections (); | ||
2430 | return; | ||
2431 | } | ||
2432 | |||
2433 | /* Is this a forward or backward ACK? | ||
2434 | * Note: a poll should never be needed in a loopback case, | ||
2435 | * since there is no possiblility of packet loss there, so | ||
2436 | * this way of discerining FWD/BCK should not be a problem. | ||
2437 | */ | ||
2438 | if (get_next_hop (c) == peer) | ||
2439 | { | ||
2440 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
2441 | fc = &c->fwd_fc; | ||
2442 | } | ||
2443 | else if (get_prev_hop (c) == peer) | ||
2444 | { | ||
2445 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
2446 | fc = &c->bck_fc; | ||
2447 | } | ||
2448 | else | ||
2449 | { | ||
2450 | GNUNET_break_op (0); | ||
2451 | return; | ||
2452 | } | ||
2453 | 642 | ||
2454 | pid = msg->cemi; | 643 | cc->task = NULL; |
644 | GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state); | ||
2455 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 645 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2456 | " PID %u, OLD %u\n", | 646 | "Sending CONNECTION_CREATE_ACK message for %s\n", |
2457 | ntohl (pid.pid), | 647 | GCC_2s (cc)); |
2458 | ntohl (fc->last_pid_recv.pid)); | 648 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
2459 | fc->last_pid_recv = pid; | 649 | env = GNUNET_MQ_msg (ack_msg, |
2460 | fwd = fc == &c->bck_fc; | 650 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); |
2461 | GCC_send_ack (c, fwd, GNUNET_YES); | 651 | ack_msg->cid = cc->cid; |
2462 | GCC_check_connections (); | 652 | cc->env = env; |
653 | update_state (cc, | ||
654 | CADET_CONNECTION_READY, | ||
655 | GNUNET_NO); | ||
656 | GCP_send (cc->mq_man, | ||
657 | env); | ||
2463 | } | 658 | } |
2464 | 659 | ||
2465 | 660 | ||
2466 | /** | 661 | /** |
2467 | * Check the message against internal state and test if it goes FWD or BCK. | 662 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a |
2468 | * | 663 | * connection that we already have. Either our ACK got lost |
2469 | * Updates the PID, state and timeout values for the connection. | 664 | * or something is fishy. Consider retransmitting the ACK. |
2470 | * | ||
2471 | * @param message Message to check. It must belong to an existing connection. | ||
2472 | * @param cid Connection ID (even if @a c is NULL, the ID is still needed). | ||
2473 | * @param c Connection this message should belong. If NULL, check fails. | ||
2474 | * @param sender Neighbor that sent the message. | ||
2475 | * | 665 | * |
2476 | * @return #GNUNET_YES if the message goes FWD. | 666 | * @param cc connection that got the duplicate CREATE |
2477 | * #GNUNET_NO if it goes BCK. | ||
2478 | * #GNUNET_SYSERR if there is an error (unauthorized sender, ...). | ||
2479 | */ | 667 | */ |
2480 | static int | 668 | void |
2481 | check_message (const struct GNUNET_MessageHeader *message, | 669 | GCC_handle_duplicate_create (struct CadetConnection *cc) |
2482 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid, | ||
2483 | struct CadetConnection *c, | ||
2484 | struct CadetPeer *sender, | ||
2485 | struct CadetEncryptedMessageIdentifier pid) | ||
2486 | { | 670 | { |
2487 | struct CadetFlowControl *fc; | 671 | if (GNUNET_YES == cc->mqm_ready) |
2488 | struct CadetPeer *hop; | ||
2489 | int fwd; | ||
2490 | uint16_t type; | ||
2491 | |||
2492 | /* Check connection */ | ||
2493 | if (NULL == c) | ||
2494 | { | 672 | { |
2495 | GNUNET_STATISTICS_update (stats, | ||
2496 | "# unknown connection", | ||
2497 | 1, GNUNET_NO); | ||
2498 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 673 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2499 | "%s on unknown connection %s\n", | 674 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", |
2500 | GC_m2s (ntohs (message->type)), | 675 | GCC_2s (cc), |
2501 | GNUNET_sh2s (&cid->connection_of_tunnel)); | 676 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); |
2502 | GNUNET_break_op (0); | 677 | /* Revert back to the state of having only received the 'CREATE', |
2503 | send_broken_unknown (cid, | 678 | and immediately proceed to send the CREATE_ACK. */ |
2504 | &my_full_id, | 679 | update_state (cc, |
2505 | NULL, | 680 | CADET_CONNECTION_CREATE_RECEIVED, |
2506 | sender); | 681 | cc->mqm_ready); |
2507 | return GNUNET_SYSERR; | 682 | if (NULL != cc->task) |
2508 | } | 683 | GNUNET_SCHEDULER_cancel (cc->task); |
2509 | 684 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | |
2510 | /* Check if origin is as expected */ | 685 | cc); |
2511 | hop = get_prev_hop (c); | ||
2512 | if (sender == hop) | ||
2513 | { | ||
2514 | fwd = GNUNET_YES; | ||
2515 | } | 686 | } |
2516 | else | 687 | else |
2517 | { | 688 | { |
2518 | hop = get_next_hop (c); | 689 | /* We are currently sending something else back, which |
2519 | GNUNET_break (hop == c->next_peer); | 690 | can only be an ACK or payload, either of which would |
2520 | if (sender == hop) | 691 | do. So actually no need to do anything. */ |
2521 | { | 692 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2522 | fwd = GNUNET_NO; | 693 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", |
2523 | } | 694 | GCC_2s (cc)); |
2524 | else | ||
2525 | { | ||
2526 | /* Unexpected peer sending traffic on a connection. */ | ||
2527 | GNUNET_break_op (0); | ||
2528 | return GNUNET_SYSERR; | ||
2529 | } | ||
2530 | } | ||
2531 | |||
2532 | /* Check PID for payload messages */ | ||
2533 | type = ntohs (message->type); | ||
2534 | if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type) | ||
2535 | { | ||
2536 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
2537 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n", | ||
2538 | ntohl (pid.pid), | ||
2539 | ntohl (fc->last_pid_recv.pid) + 1, | ||
2540 | ntohl (fc->last_ack_sent.pid)); | ||
2541 | if (GC_is_pid_bigger (ntohl (pid.pid), | ||
2542 | ntohl (fc->last_ack_sent.pid))) | ||
2543 | { | ||
2544 | GNUNET_STATISTICS_update (stats, | ||
2545 | "# unsolicited message", | ||
2546 | 1, | ||
2547 | GNUNET_NO); | ||
2548 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2549 | "Received PID %u, (prev %u), ACK %u\n", | ||
2550 | pid, fc->last_pid_recv, fc->last_ack_sent); | ||
2551 | return GNUNET_SYSERR; | ||
2552 | } | ||
2553 | if (GC_is_pid_bigger (ntohl (pid.pid), | ||
2554 | ntohl (fc->last_pid_recv.pid))) | ||
2555 | { | ||
2556 | unsigned int delta; | ||
2557 | |||
2558 | delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid); | ||
2559 | fc->last_pid_recv = pid; | ||
2560 | fc->recv_bitmap <<= delta; | ||
2561 | fc->recv_bitmap |= 1; | ||
2562 | } | ||
2563 | else | ||
2564 | { | ||
2565 | GNUNET_STATISTICS_update (stats, | ||
2566 | "# out of order PID", | ||
2567 | 1, | ||
2568 | GNUNET_NO); | ||
2569 | if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, | ||
2570 | pid, | ||
2571 | fc->recv_bitmap)) | ||
2572 | { | ||
2573 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2574 | "PID %u unexpected (%u+), dropping!\n", | ||
2575 | ntohl (pid.pid), | ||
2576 | ntohl (fc->last_pid_recv.pid) - 31); | ||
2577 | return GNUNET_SYSERR; | ||
2578 | } | ||
2579 | fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, | ||
2580 | pid); | ||
2581 | } | ||
2582 | } | ||
2583 | |||
2584 | /* Count as connection confirmation. */ | ||
2585 | if ( (CADET_CONNECTION_SENT == c->state) || | ||
2586 | (CADET_CONNECTION_ACK == c->state) ) | ||
2587 | { | ||
2588 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2589 | if (NULL != c->t) | ||
2590 | { | ||
2591 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2592 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2593 | } | ||
2594 | } | 695 | } |
2595 | connection_reset_timeout (c, fwd); | ||
2596 | |||
2597 | return fwd; | ||
2598 | } | 696 | } |
2599 | 697 | ||
2600 | 698 | ||
2601 | /** | 699 | /** |
2602 | * Handler for key exchange traffic (Axolotl KX). | 700 | * There has been a change in the message queue existence for our |
701 | * peer at the first hop. Adjust accordingly. | ||
2603 | * | 702 | * |
2604 | * @param peer Message sender (neighbor). | 703 | * @param cls the `struct CadetConnection` |
2605 | * @param msg Message itself. | 704 | * @param available #GNUNET_YES if sending is now possible, |
705 | * #GNUNET_NO if sending is no longer possible | ||
706 | * #GNUNET_SYSERR if sending is no longer possible | ||
707 | * and the last envelope was discarded | ||
2606 | */ | 708 | */ |
2607 | void | 709 | static void |
2608 | GCC_handle_kx (struct CadetPeer *peer, | 710 | manage_first_hop_mq (void *cls, |
2609 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 711 | int available) |
2610 | { | 712 | { |
2611 | static struct CadetEncryptedMessageIdentifier zero; | 713 | struct CadetConnection *cc = cls; |
2612 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid; | ||
2613 | struct CadetConnection *c; | ||
2614 | int fwd; | ||
2615 | |||
2616 | GCC_check_connections (); | ||
2617 | cid = &msg->cid; | ||
2618 | log_message (&msg->header, peer, cid); | ||
2619 | |||
2620 | c = connection_get (cid); | ||
2621 | fwd = check_message (&msg->header, | ||
2622 | cid, | ||
2623 | c, | ||
2624 | peer, | ||
2625 | zero); | ||
2626 | |||
2627 | /* If something went wrong, discard message. */ | ||
2628 | if (GNUNET_SYSERR == fwd) | ||
2629 | { | ||
2630 | GNUNET_break_op (0); | ||
2631 | GCC_check_connections (); | ||
2632 | return; | ||
2633 | } | ||
2634 | 714 | ||
2635 | /* Is this message for us? */ | 715 | if (GNUNET_YES != available) |
2636 | if (GCC_is_terminal (c, fwd)) | ||
2637 | { | 716 | { |
2638 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | 717 | /* Connection is down, for now... */ |
2639 | GNUNET_STATISTICS_update (stats, "# received KX", 1, GNUNET_NO); | 718 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2640 | if (NULL == c->t) | 719 | "Core MQ for %s went down\n", |
720 | GCC_2s (cc)); | ||
721 | update_state (cc, | ||
722 | CADET_CONNECTION_NEW, | ||
723 | GNUNET_NO); | ||
724 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
725 | if (NULL != cc->task) | ||
2641 | { | 726 | { |
2642 | GNUNET_break (0); | 727 | GNUNET_SCHEDULER_cancel (cc->task); |
2643 | return; | 728 | cc->task = NULL; |
2644 | } | 729 | } |
2645 | GCT_handle_kx (c->t, msg); | ||
2646 | GCC_check_connections (); | ||
2647 | return; | ||
2648 | } | ||
2649 | |||
2650 | /* Message not for us: forward to next hop */ | ||
2651 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2652 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2653 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2654 | zero, c, fwd, | ||
2655 | GNUNET_NO, NULL, NULL); | ||
2656 | GCC_check_connections (); | ||
2657 | } | ||
2658 | |||
2659 | |||
2660 | /** | ||
2661 | * Handler for encrypted cadet network traffic (channel mgmt, data). | ||
2662 | * | ||
2663 | * @param peer Message sender (neighbor). | ||
2664 | * @param msg Message itself. | ||
2665 | */ | ||
2666 | void | ||
2667 | GCC_handle_encrypted (struct CadetPeer *peer, | ||
2668 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
2669 | { | ||
2670 | static struct CadetEncryptedMessageIdentifier zero; | ||
2671 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid; | ||
2672 | struct CadetConnection *c; | ||
2673 | struct CadetEncryptedMessageIdentifier pid; | ||
2674 | int fwd; | ||
2675 | |||
2676 | GCC_check_connections (); | ||
2677 | cid = &msg->cid; | ||
2678 | pid = msg->cemi; | ||
2679 | log_message (&msg->header, peer, cid); | ||
2680 | |||
2681 | c = connection_get (cid); | ||
2682 | fwd = check_message (&msg->header, | ||
2683 | cid, | ||
2684 | c, | ||
2685 | peer, | ||
2686 | pid); | ||
2687 | |||
2688 | /* If something went wrong, discard message. */ | ||
2689 | if (GNUNET_SYSERR == fwd) | ||
2690 | { | ||
2691 | GCC_check_connections (); | ||
2692 | return; | 730 | return; |
2693 | } | 731 | } |
2694 | 732 | ||
2695 | /* Is this message for us? */ | 733 | update_state (cc, |
2696 | if (GCC_is_terminal (c, fwd)) | 734 | cc->state, |
2697 | { | 735 | GNUNET_YES); |
2698 | GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO); | 736 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2699 | 737 | "Core MQ for %s became available in state %d\n", | |
2700 | if (NULL == c->t) | 738 | GCC_2s (cc), |
739 | cc->state); | ||
740 | switch (cc->state) | ||
741 | { | ||
742 | case CADET_CONNECTION_NEW: | ||
743 | /* Transmit immediately */ | ||
744 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | ||
745 | cc); | ||
746 | break; | ||
747 | case CADET_CONNECTION_SENDING_CREATE: | ||
748 | /* Should not be possible to be called in this state. */ | ||
749 | GNUNET_assert (0); | ||
750 | break; | ||
751 | case CADET_CONNECTION_SENT: | ||
752 | /* Retry a bit later... */ | ||
753 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
754 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
755 | &send_create, | ||
756 | cc); | ||
757 | break; | ||
758 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
759 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
760 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
761 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
762 | cc); | ||
763 | break; | ||
764 | case CADET_CONNECTION_READY: | ||
765 | if ( (NULL == cc->keepalive_qe) && | ||
766 | (GNUNET_YES == cc->mqm_ready) && | ||
767 | (NULL == cc->task) ) | ||
2701 | { | 768 | { |
2702 | GNUNET_break (GNUNET_NO != c->destroy); | 769 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2703 | return; | 770 | "Scheduling keepalive for %s in %s\n", |
771 | GCC_2s (cc), | ||
772 | GNUNET_STRINGS_relative_time_to_string (keepalive_period, | ||
773 | GNUNET_YES)); | ||
774 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
775 | &send_keepalive, | ||
776 | cc); | ||
2704 | } | 777 | } |
2705 | GCT_handle_encrypted (c->t, msg); | 778 | break; |
2706 | GCC_send_ack (c, fwd, GNUNET_NO); | ||
2707 | GCC_check_connections (); | ||
2708 | return; | ||
2709 | } | 779 | } |
2710 | |||
2711 | /* Message not for us: forward to next hop */ | ||
2712 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2713 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2714 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2715 | zero, c, fwd, | ||
2716 | GNUNET_NO, NULL, NULL); | ||
2717 | GCC_check_connections (); | ||
2718 | } | 780 | } |
2719 | 781 | ||
2720 | 782 | ||
2721 | /** | 783 | /** |
2722 | * Initialize the connections subsystem | 784 | * Create a connection to @a destination via @a path and notify @a cb |
785 | * whenever we are ready for more data. Shared logic independent of | ||
786 | * who is initiating the connection. | ||
2723 | * | 787 | * |
2724 | * @param c Configuration handle. | 788 | * @param destination where to go |
789 | * @param path which path to take (may not be the full path) | ||
790 | * @param off offset of @a destination on @a path | ||
791 | * @param options options for the connection | ||
792 | * @param ct which tunnel uses this connection | ||
793 | * @param init_state initial state for the connection | ||
794 | * @param ready_cb function to call when ready to transmit | ||
795 | * @param ready_cb_cls closure for @a cb | ||
796 | * @return handle to the connection | ||
2725 | */ | 797 | */ |
2726 | void | 798 | static struct CadetConnection * |
2727 | GCC_init (const struct GNUNET_CONFIGURATION_Handle *c) | 799 | connection_create (struct CadetPeer *destination, |
2728 | { | 800 | struct CadetPeerPath *path, |
2729 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | 801 | unsigned int off, |
2730 | if (GNUNET_OK != | 802 | enum GNUNET_CADET_ChannelOption options, |
2731 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE", | 803 | struct CadetTConnection *ct, |
2732 | &max_msgs_queue)) | 804 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
2733 | { | 805 | enum CadetConnectionState init_state, |
2734 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | 806 | GCC_ReadyCallback ready_cb, |
2735 | "CADET", "MAX_MSGS_QUEUE", "MISSING"); | 807 | void *ready_cb_cls) |
2736 | GNUNET_SCHEDULER_shutdown (); | 808 | { |
2737 | return; | 809 | struct CadetConnection *cc; |
2738 | } | 810 | struct CadetPeer *first_hop; |
2739 | 811 | ||
2740 | if (GNUNET_OK != | 812 | cc = GNUNET_new (struct CadetConnection); |
2741 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS", | 813 | cc->options = options; |
2742 | &max_connections)) | 814 | cc->state = init_state; |
2743 | { | 815 | cc->ct = ct; |
2744 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | 816 | cc->cid = *cid; |
2745 | "CADET", "MAX_CONNECTIONS", "MISSING"); | ||
2746 | GNUNET_SCHEDULER_shutdown (); | ||
2747 | return; | ||
2748 | } | ||
2749 | |||
2750 | if (GNUNET_OK != | ||
2751 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME", | ||
2752 | &refresh_connection_time)) | ||
2753 | { | ||
2754 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2755 | "CADET", "REFRESH_CONNECTION_TIME", "MISSING"); | ||
2756 | GNUNET_SCHEDULER_shutdown (); | ||
2757 | return; | ||
2758 | } | ||
2759 | create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
2760 | refresh_connection_time); | ||
2761 | connections = GNUNET_CONTAINER_multishortmap_create (1024, | ||
2762 | GNUNET_YES); | ||
2763 | } | ||
2764 | |||
2765 | |||
2766 | /** | ||
2767 | * Destroy each connection on shutdown. | ||
2768 | * | ||
2769 | * @param cls Closure (unused). | ||
2770 | * @param key Current key code (CID, unused). | ||
2771 | * @param value Value in the hash map (`struct CadetConnection`) | ||
2772 | * | ||
2773 | * @return #GNUNET_YES, because we should continue to iterate | ||
2774 | */ | ||
2775 | static int | ||
2776 | shutdown_iterator (void *cls, | ||
2777 | const struct GNUNET_ShortHashCode *key, | ||
2778 | void *value) | ||
2779 | { | ||
2780 | struct CadetConnection *c = value; | ||
2781 | |||
2782 | c->state = CADET_CONNECTION_DESTROYED; | ||
2783 | GCC_destroy (c); | ||
2784 | return GNUNET_YES; | ||
2785 | } | ||
2786 | |||
2787 | |||
2788 | /** | ||
2789 | * Shut down the connections subsystem. | ||
2790 | */ | ||
2791 | void | ||
2792 | GCC_shutdown (void) | ||
2793 | { | ||
2794 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n"); | ||
2795 | GCC_check_connections (); | ||
2796 | GNUNET_CONTAINER_multishortmap_iterate (connections, | ||
2797 | &shutdown_iterator, | ||
2798 | NULL); | ||
2799 | GNUNET_CONTAINER_multishortmap_destroy (connections); | ||
2800 | connections = NULL; | ||
2801 | } | ||
2802 | |||
2803 | |||
2804 | /** | ||
2805 | * Create a connection. | ||
2806 | * | ||
2807 | * @param cid Connection ID (either created locally or imposed remotely). | ||
2808 | * @param t Tunnel this connection belongs to (or NULL for transit connections); | ||
2809 | * @param path Path this connection has to use (copy is made). | ||
2810 | * @param own_pos Own position in the @c path path. | ||
2811 | * | ||
2812 | * @return Newly created connection. | ||
2813 | * NULL in case of error: own id not in path, wrong neighbors, ... | ||
2814 | */ | ||
2815 | struct CadetConnection * | ||
2816 | GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
2817 | struct CadetTunnel *t, | ||
2818 | struct CadetPeerPath *path, | ||
2819 | unsigned int own_pos) | ||
2820 | { | ||
2821 | struct CadetConnection *c; | ||
2822 | struct CadetPeerPath *cpath; | ||
2823 | |||
2824 | GCC_check_connections (); | ||
2825 | cpath = path_duplicate (path); | ||
2826 | GNUNET_assert (NULL != cpath); | ||
2827 | c = GNUNET_new (struct CadetConnection); | ||
2828 | c->id = *cid; | ||
2829 | GNUNET_assert (GNUNET_OK == | 817 | GNUNET_assert (GNUNET_OK == |
2830 | GNUNET_CONTAINER_multishortmap_put (connections, | 818 | GNUNET_CONTAINER_multishortmap_put (connections, |
2831 | &c->id.connection_of_tunnel, | 819 | &GCC_get_id (cc)->connection_of_tunnel, |
2832 | c, | 820 | cc, |
2833 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 821 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
2834 | fc_init (&c->fwd_fc); | 822 | cc->ready_cb = ready_cb; |
2835 | fc_init (&c->bck_fc); | 823 | cc->ready_cb_cls = ready_cb_cls; |
2836 | c->fwd_fc.c = c; | 824 | cc->path = path; |
2837 | c->bck_fc.c = c; | 825 | cc->off = off; |
2838 | |||
2839 | c->t = t; | ||
2840 | GNUNET_assert (own_pos <= cpath->length - 1); | ||
2841 | c->own_pos = own_pos; | ||
2842 | c->path = cpath; | ||
2843 | cpath->c = c; | ||
2844 | if (GNUNET_OK != register_neighbors (c)) | ||
2845 | { | ||
2846 | if (0 == own_pos) | ||
2847 | { | ||
2848 | /* We were the origin of this request, this means we have invalid | ||
2849 | * info about the paths to reach the destination. We must invalidate | ||
2850 | * the *original* path to avoid trying it again in the next minute. | ||
2851 | */ | ||
2852 | if (2 < path->length) | ||
2853 | path_invalidate (path); | ||
2854 | else | ||
2855 | { | ||
2856 | GNUNET_break (0); | ||
2857 | GCT_debug(t, GNUNET_ERROR_TYPE_WARNING); | ||
2858 | } | ||
2859 | c->t = NULL; | ||
2860 | } | ||
2861 | path_destroy (c->path); | ||
2862 | c->path = NULL; | ||
2863 | GCC_destroy (c); | ||
2864 | return NULL; | ||
2865 | } | ||
2866 | LOG (GNUNET_ERROR_TYPE_INFO, "New connection %s\n", GCC_2s (c)); | ||
2867 | GCC_check_connections (); | ||
2868 | return c; | ||
2869 | } | ||
2870 | |||
2871 | |||
2872 | /** | ||
2873 | * Connection is no longer needed: destroy it. | ||
2874 | * | ||
2875 | * Cancels all pending traffic (including possible DESTROY messages), all | ||
2876 | * maintenance tasks and removes the connection from neighbor peers and tunnel. | ||
2877 | * | ||
2878 | * @param c Connection to destroy. | ||
2879 | */ | ||
2880 | void | ||
2881 | GCC_destroy (struct CadetConnection *c) | ||
2882 | { | ||
2883 | GCC_check_connections (); | ||
2884 | if (NULL == c) | ||
2885 | { | ||
2886 | GNUNET_break (0); | ||
2887 | return; | ||
2888 | } | ||
2889 | |||
2890 | if (2 == c->destroy) /* cancel queues -> GCP_queue_cancel -> q_destroy -> */ | ||
2891 | return; /* -> message_sent -> GCC_destroy. Don't loop. */ | ||
2892 | c->destroy = 2; | ||
2893 | |||
2894 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2895 | "destroying connection %s\n", | ||
2896 | GCC_2s (c)); | ||
2897 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2898 | " fc's f: %p, b: %p\n", | ||
2899 | &c->fwd_fc, &c->bck_fc); | ||
2900 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2901 | " fc tasks f: %u, b: %u\n", | ||
2902 | c->fwd_fc.poll_task, | ||
2903 | c->bck_fc.poll_task); | ||
2904 | |||
2905 | /* Cancel all traffic */ | ||
2906 | if (NULL != c->path) | ||
2907 | { | ||
2908 | connection_cancel_queues (c, GNUNET_YES); | ||
2909 | connection_cancel_queues (c, GNUNET_NO); | ||
2910 | if (NULL != c->maintenance_q) | ||
2911 | { | ||
2912 | GCP_send_cancel (c->maintenance_q); | ||
2913 | c->maintenance_q = NULL; | ||
2914 | } | ||
2915 | } | ||
2916 | unregister_neighbors (c); | ||
2917 | path_destroy (c->path); | ||
2918 | c->path = NULL; | ||
2919 | |||
2920 | /* Delete from tunnel */ | ||
2921 | if (NULL != c->t) | ||
2922 | GCT_remove_connection (c->t, c); | ||
2923 | |||
2924 | if (NULL != c->check_duplicates_task) | ||
2925 | GNUNET_SCHEDULER_cancel (c->check_duplicates_task); | ||
2926 | if (NULL != c->fwd_maintenance_task) | ||
2927 | GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); | ||
2928 | if (NULL != c->bck_maintenance_task) | ||
2929 | GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); | ||
2930 | |||
2931 | if (GNUNET_NO == c->was_removed) | ||
2932 | { | ||
2933 | GNUNET_break (GNUNET_YES == | ||
2934 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
2935 | &c->id.connection_of_tunnel, | ||
2936 | c)); | ||
2937 | } | ||
2938 | GNUNET_STATISTICS_update (stats, | ||
2939 | "# connections", | ||
2940 | -1, | ||
2941 | GNUNET_NO); | ||
2942 | GNUNET_free (c); | ||
2943 | GCC_check_connections (); | ||
2944 | } | ||
2945 | |||
2946 | |||
2947 | /** | ||
2948 | * Get the connection ID. | ||
2949 | * | ||
2950 | * @param c Connection to get the ID from. | ||
2951 | * | ||
2952 | * @return ID of the connection. | ||
2953 | */ | ||
2954 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
2955 | GCC_get_id (const struct CadetConnection *c) | ||
2956 | { | ||
2957 | return &c->id; | ||
2958 | } | ||
2959 | |||
2960 | |||
2961 | /** | ||
2962 | * Get the connection path. | ||
2963 | * | ||
2964 | * @param c Connection to get the path from. | ||
2965 | * | ||
2966 | * @return path used by the connection. | ||
2967 | */ | ||
2968 | const struct CadetPeerPath * | ||
2969 | GCC_get_path (const struct CadetConnection *c) | ||
2970 | { | ||
2971 | if (GNUNET_NO == c->destroy) | ||
2972 | return c->path; | ||
2973 | return NULL; | ||
2974 | } | ||
2975 | |||
2976 | |||
2977 | /** | ||
2978 | * Get the connection state. | ||
2979 | * | ||
2980 | * @param c Connection to get the state from. | ||
2981 | * | ||
2982 | * @return state of the connection. | ||
2983 | */ | ||
2984 | enum CadetConnectionState | ||
2985 | GCC_get_state (const struct CadetConnection *c) | ||
2986 | { | ||
2987 | return c->state; | ||
2988 | } | ||
2989 | |||
2990 | /** | ||
2991 | * Get the connection tunnel. | ||
2992 | * | ||
2993 | * @param c Connection to get the tunnel from. | ||
2994 | * | ||
2995 | * @return tunnel of the connection. | ||
2996 | */ | ||
2997 | struct CadetTunnel * | ||
2998 | GCC_get_tunnel (const struct CadetConnection *c) | ||
2999 | { | ||
3000 | return c->t; | ||
3001 | } | ||
3002 | |||
3003 | |||
3004 | /** | ||
3005 | * Get free buffer space in a connection. | ||
3006 | * | ||
3007 | * @param c Connection. | ||
3008 | * @param fwd Is query about FWD traffic? | ||
3009 | * | ||
3010 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
3011 | */ | ||
3012 | unsigned int | ||
3013 | GCC_get_buffer (struct CadetConnection *c, int fwd) | ||
3014 | { | ||
3015 | struct CadetFlowControl *fc; | ||
3016 | |||
3017 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3018 | |||
3019 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Get %s buffer on %s: %u - %u\n", | ||
3020 | GC_f2s (fwd), GCC_2s (c), fc->queue_max, fc->queue_n); | ||
3021 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | ||
3022 | |||
3023 | return (fc->queue_max - fc->queue_n); | ||
3024 | } | ||
3025 | |||
3026 | |||
3027 | /** | ||
3028 | * Get how many messages have we allowed to send to us from a direction. | ||
3029 | * | ||
3030 | * @param c Connection. | ||
3031 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | ||
3032 | * | ||
3033 | * @return last_ack_sent - last_pid_recv | ||
3034 | */ | ||
3035 | unsigned int | ||
3036 | GCC_get_allowed (struct CadetConnection *c, int fwd) | ||
3037 | { | ||
3038 | struct CadetFlowControl *fc; | ||
3039 | |||
3040 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3041 | if ( (CADET_CONNECTION_READY != c->state) || | ||
3042 | GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid), | ||
3043 | ntohl (fc->last_ack_sent.pid)) ) | ||
3044 | { | ||
3045 | return 0; | ||
3046 | } | ||
3047 | return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid)); | ||
3048 | } | ||
3049 | |||
3050 | |||
3051 | /** | ||
3052 | * Get messages queued in a connection. | ||
3053 | * | ||
3054 | * @param c Connection. | ||
3055 | * @param fwd Is query about FWD traffic? | ||
3056 | * | ||
3057 | * @return Number of messages queued. | ||
3058 | */ | ||
3059 | unsigned int | ||
3060 | GCC_get_qn (struct CadetConnection *c, int fwd) | ||
3061 | { | ||
3062 | struct CadetFlowControl *fc; | ||
3063 | |||
3064 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3065 | |||
3066 | return fc->queue_n; | ||
3067 | } | ||
3068 | |||
3069 | |||
3070 | /** | ||
3071 | * Get next PID to use. | ||
3072 | * | ||
3073 | * @param c Connection. | ||
3074 | * @param fwd Is query about FWD traffic? | ||
3075 | * @return Next PID to use. | ||
3076 | */ | ||
3077 | struct CadetEncryptedMessageIdentifier | ||
3078 | GCC_get_pid (struct CadetConnection *c, int fwd) | ||
3079 | { | ||
3080 | struct CadetFlowControl *fc; | ||
3081 | struct CadetEncryptedMessageIdentifier pid; | ||
3082 | |||
3083 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3084 | pid = fc->next_pid; | ||
3085 | fc->next_pid.pid = htonl (1 + ntohl (pid.pid)); | ||
3086 | return pid; | ||
3087 | } | ||
3088 | |||
3089 | |||
3090 | /** | ||
3091 | * Allow the connection to advertise a buffer of the given size. | ||
3092 | * | ||
3093 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
3094 | * allowing up to last_pid_recv + buffer. | ||
3095 | * | ||
3096 | * @param c Connection. | ||
3097 | * @param buffer How many more messages the connection can accept. | ||
3098 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
3099 | */ | ||
3100 | void | ||
3101 | GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd) | ||
3102 | { | ||
3103 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n", | ||
3104 | GCC_2s (c), buffer, GC_f2s (fwd)); | ||
3105 | send_ack (c, buffer, fwd, GNUNET_NO); | ||
3106 | } | ||
3107 | |||
3108 | |||
3109 | /** | ||
3110 | * Notify other peers on a connection of a broken link. Mark connections | ||
3111 | * to destroy after all traffic has been sent. | ||
3112 | * | ||
3113 | * @param c Connection on which there has been a disconnection. | ||
3114 | * @param peer Peer that disconnected. | ||
3115 | */ | ||
3116 | void | ||
3117 | GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer) | ||
3118 | { | ||
3119 | struct CadetFlowControl *fc; | ||
3120 | char peer_name[16]; | ||
3121 | int fwd; | ||
3122 | |||
3123 | GCC_check_connections (); | ||
3124 | strncpy (peer_name, GCP_2s (peer), 16); | ||
3125 | peer_name[15] = '\0'; | ||
3126 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 826 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3127 | "shutting down %s, %s disconnected\n", | 827 | "Creating %s using path %s\n", |
3128 | GCC_2s (c), peer_name); | 828 | GCC_2s (cc), |
3129 | 829 | GCPP_2s (path)); | |
3130 | invalidate_paths (c, peer); | 830 | GCPP_add_connection (path, |
3131 | 831 | off, | |
3132 | fwd = is_fwd (c, peer); | 832 | cc); |
3133 | if (GNUNET_SYSERR == fwd) | 833 | for (unsigned int i=0;i<off;i++) |
3134 | { | 834 | GCP_add_connection (GCPP_get_peer_at_offset (path, |
3135 | GNUNET_break (0); | 835 | i), |
3136 | return; | 836 | cc); |
3137 | } | 837 | |
3138 | if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) || | 838 | first_hop = GCPP_get_peer_at_offset (path, |
3139 | (GNUNET_NO != c->destroy) ) | 839 | 0); |
3140 | { | 840 | cc->mq_man = GCP_request_mq (first_hop, |
3141 | /* Local shutdown, or other peer already down (hence 'c->destroy'); | 841 | &manage_first_hop_mq, |
3142 | so there is no one to notify about this, just clean up. */ | 842 | cc); |
3143 | GCC_destroy (c); | 843 | return cc; |
3144 | GCC_check_connections (); | 844 | } |
3145 | return; | 845 | |
3146 | } | 846 | |
3147 | /* Mark FlowControl towards the peer as unavaliable. */ | 847 | /** |
3148 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | 848 | * Create a connection to @a destination via @a path and |
3149 | fc->queue_max = 0; | 849 | * notify @a cb whenever we are ready for more data. This |
3150 | 850 | * is an inbound tunnel, so we must use the existing @a cid | |
3151 | send_broken (c, &my_full_id, GCP_get_id (peer), fwd); | 851 | * |
3152 | 852 | * @param destination where to go | |
3153 | /* Connection will have at least one pending message | 853 | * @param path which path to take (may not be the full path) |
3154 | * (the one we just scheduled), so delay destruction | 854 | * @param options options for the connection |
3155 | * and remove from map so we don't use accidentally. */ | 855 | * @param ct which tunnel uses this connection |
3156 | mark_destroyed (c); | 856 | * @param ready_cb function to call when ready to transmit |
3157 | GNUNET_assert (GNUNET_NO == c->was_removed); | 857 | * @param ready_cb_cls closure for @a cb |
3158 | c->was_removed = GNUNET_YES; | 858 | * @return handle to the connection, NULL if we already have |
3159 | GNUNET_break (GNUNET_YES == | 859 | * a connection that takes precedence on @a path |
3160 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
3161 | &c->id.connection_of_tunnel, | ||
3162 | c)); | ||
3163 | /* Cancel queue in the direction that just died. */ | ||
3164 | connection_cancel_queues (c, ! fwd); | ||
3165 | GCC_stop_poll (c, ! fwd); | ||
3166 | unregister_neighbors (c); | ||
3167 | GCC_check_connections (); | ||
3168 | } | ||
3169 | |||
3170 | |||
3171 | /** | ||
3172 | * Is this peer the first one on the connection? | ||
3173 | * | ||
3174 | * @param c Connection. | ||
3175 | * @param fwd Is this about fwd traffic? | ||
3176 | * | ||
3177 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
3178 | */ | 860 | */ |
3179 | int | 861 | struct CadetConnection * |
3180 | GCC_is_origin (struct CadetConnection *c, int fwd) | 862 | GCC_create_inbound (struct CadetPeer *destination, |
3181 | { | 863 | struct CadetPeerPath *path, |
3182 | if (!fwd && c->path->length - 1 == c->own_pos ) | 864 | enum GNUNET_CADET_ChannelOption options, |
3183 | return GNUNET_YES; | 865 | struct CadetTConnection *ct, |
3184 | if (fwd && 0 == c->own_pos) | 866 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
3185 | return GNUNET_YES; | 867 | GCC_ReadyCallback ready_cb, |
3186 | return GNUNET_NO; | 868 | void *ready_cb_cls) |
3187 | } | 869 | { |
3188 | 870 | struct CadetConnection *cc; | |
3189 | 871 | unsigned int off; | |
3190 | /** | 872 | |
3191 | * Is this peer the last one on the connection? | 873 | off = GCPP_find_peer (path, |
3192 | * | 874 | destination); |
3193 | * @param c Connection. | 875 | GNUNET_assert (UINT_MAX != off); |
3194 | * @param fwd Is this about fwd traffic? | 876 | cc = GCPP_get_connection (path, |
3195 | * Note that the ROOT is the terminal for BCK traffic! | 877 | destination, |
3196 | * | 878 | off); |
3197 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | 879 | if (NULL != cc) |
3198 | */ | 880 | { |
3199 | int | 881 | int cmp; |
3200 | GCC_is_terminal (struct CadetConnection *c, int fwd) | 882 | |
3201 | { | 883 | cmp = memcmp (cid, |
3202 | return GCC_is_origin (c, ! fwd); | 884 | &cc->cid, |
3203 | } | 885 | sizeof (*cid)); |
3204 | 886 | if (0 == cmp) | |
3205 | 887 | { | |
3206 | /** | 888 | /* Two peers picked the SAME random connection identifier at the |
3207 | * See if we are allowed to send by the next hop in the given direction. | 889 | same time for the same path? Must be malicious. Drop |
3208 | * | 890 | connection (existing and inbound), even if it is the only |
3209 | * @param c Connection. | 891 | one. */ |
3210 | * @param fwd Is this about fwd traffic? | 892 | GNUNET_break_op (0); |
3211 | * | 893 | GCT_connection_lost (cc->ct); |
3212 | * @return #GNUNET_YES in case it's OK to send. | 894 | GCC_destroy_without_tunnel (cc); |
3213 | */ | ||
3214 | int | ||
3215 | GCC_is_sendable (struct CadetConnection *c, int fwd) | ||
3216 | { | ||
3217 | struct CadetFlowControl *fc; | ||
3218 | |||
3219 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3220 | " checking sendability of %s traffic on %s\n", | ||
3221 | GC_f2s (fwd), GCC_2s (c)); | ||
3222 | if (NULL == c) | ||
3223 | { | ||
3224 | GNUNET_break (0); | ||
3225 | return GNUNET_YES; | ||
3226 | } | ||
3227 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3228 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3229 | " last ack recv: %u, last pid sent: %u\n", | ||
3230 | ntohl (fc->last_ack_recv.pid), | ||
3231 | ntohl (fc->last_pid_sent.pid)); | ||
3232 | if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid), | ||
3233 | ntohl (fc->last_pid_sent.pid))) | ||
3234 | { | ||
3235 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n"); | ||
3236 | return GNUNET_YES; | ||
3237 | } | ||
3238 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
3239 | return GNUNET_NO; | ||
3240 | } | ||
3241 | |||
3242 | |||
3243 | /** | ||
3244 | * Check if this connection is a direct one (never trim a direct connection). | ||
3245 | * | ||
3246 | * @param c Connection. | ||
3247 | * | ||
3248 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
3249 | */ | ||
3250 | int | ||
3251 | GCC_is_direct (struct CadetConnection *c) | ||
3252 | { | ||
3253 | return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO; | ||
3254 | } | ||
3255 | |||
3256 | |||
3257 | /** | ||
3258 | * Sends a completely built message on a connection, properly registering | ||
3259 | * all used resources. | ||
3260 | * | ||
3261 | * @param message Message to send. | ||
3262 | * @param payload_type Type of payload, in case the message is encrypted. | ||
3263 | * 0 for restransmissions (when type is no longer known) | ||
3264 | * UINT16_MAX when not applicable. | ||
3265 | * @param payload_id ID of the payload (PID, ACK, ...). | ||
3266 | * @param c Connection on which this message is transmitted. | ||
3267 | * @param fwd Is this a fwd message? | ||
3268 | * @param force Force the connection to accept the message (buffer overfill). | ||
3269 | * @param cont Continuation called once message is sent. Can be NULL. | ||
3270 | * @param cont_cls Closure for @c cont. | ||
3271 | * | ||
3272 | * @return Handle to cancel the message before it's sent. | ||
3273 | * NULL on error. | ||
3274 | * Invalid on @c cont call. | ||
3275 | */ | ||
3276 | struct CadetConnectionQueue * | ||
3277 | GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
3278 | uint16_t payload_type, | ||
3279 | struct CadetEncryptedMessageIdentifier payload_id, | ||
3280 | struct CadetConnection *c, int fwd, int force, | ||
3281 | GCC_sent cont, void *cont_cls) | ||
3282 | { | ||
3283 | struct CadetFlowControl *fc; | ||
3284 | struct CadetConnectionQueue *q; | ||
3285 | uint16_t size; | ||
3286 | uint16_t type; | ||
3287 | |||
3288 | size = ntohs (message->size); | ||
3289 | type = ntohs (message->type); | ||
3290 | |||
3291 | GCC_check_connections (); | ||
3292 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3293 | if (0 == fc->queue_max) | ||
3294 | { | ||
3295 | GNUNET_break (0); | ||
3296 | return NULL; | ||
3297 | } | ||
3298 | |||
3299 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
3300 | "--> %s (%s %4u) on conn %s (%p) %s [%5u]\n", | ||
3301 | GC_m2s (type), GC_m2s (payload_type), payload_id, GCC_2s (c), c, | ||
3302 | GC_f2s(fwd), size); | ||
3303 | switch (type) | ||
3304 | { | ||
3305 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
3306 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n", | ||
3307 | fc, | ||
3308 | fc->queue_n, | ||
3309 | ntohl (fc->last_pid_sent.pid), | ||
3310 | ntohl (fc->last_ack_recv.pid)); | ||
3311 | if (GNUNET_NO == force) | ||
3312 | { | ||
3313 | fc->queue_n++; | ||
3314 | } | ||
3315 | break; | ||
3316 | |||
3317 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
3318 | /* nothing to do here */ | ||
3319 | break; | ||
3320 | |||
3321 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
3322 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
3323 | /* Should've only be used for restransmissions. */ | ||
3324 | GNUNET_break (0 == payload_type); | ||
3325 | break; | ||
3326 | |||
3327 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
3328 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
3329 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
3330 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
3331 | GNUNET_assert (GNUNET_YES == force); | ||
3332 | break; | ||
3333 | |||
3334 | default: | ||
3335 | GNUNET_break (0); | ||
3336 | return NULL; | 895 | return NULL; |
3337 | } | 896 | } |
3338 | 897 | if (0 < cmp) | |
3339 | if (fc->queue_n > fc->queue_max && GNUNET_NO == force) | ||
3340 | { | ||
3341 | GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", | ||
3342 | 1, GNUNET_NO); | ||
3343 | GNUNET_break (0); | ||
3344 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n", | ||
3345 | fc->queue_n, fc->queue_max); | ||
3346 | if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type) | ||
3347 | { | 898 | { |
3348 | fc->queue_n--; | 899 | /* drop existing */ |
900 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
901 | "Got two connections on %s, dropping my existing %s\n", | ||
902 | GCPP_2s (path), | ||
903 | GCC_2s (cc)); | ||
904 | GCT_connection_lost (cc->ct); | ||
905 | GCC_destroy_without_tunnel (cc); | ||
3349 | } | 906 | } |
3350 | return NULL; /* Drop this message */ | 907 | else |
3351 | } | ||
3352 | |||
3353 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %s %u\n", | ||
3354 | GCC_2s (c), c->pending_messages); | ||
3355 | c->pending_messages++; | ||
3356 | |||
3357 | q = GNUNET_new (struct CadetConnectionQueue); | ||
3358 | q->cont = cont; | ||
3359 | q->cont_cls = cont_cls; | ||
3360 | q->forced = force; | ||
3361 | GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q); | ||
3362 | q->peer_q = GCP_send (get_hop (c, fwd), | ||
3363 | message, | ||
3364 | payload_type, | ||
3365 | payload_id, | ||
3366 | c, | ||
3367 | fwd, | ||
3368 | &conn_message_sent, q); | ||
3369 | if (NULL == q->peer_q) | ||
3370 | { | ||
3371 | LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c)); | ||
3372 | GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q); | ||
3373 | GNUNET_free (q); | ||
3374 | GCC_check_connections (); | ||
3375 | return NULL; | ||
3376 | } | ||
3377 | GCC_check_connections (); | ||
3378 | return q; | ||
3379 | } | ||
3380 | |||
3381 | |||
3382 | /** | ||
3383 | * Cancel a previously sent message while it's in the queue. | ||
3384 | * | ||
3385 | * ONLY can be called before the continuation given to the send function | ||
3386 | * is called. Once the continuation is called, the message is no longer in the | ||
3387 | * queue. | ||
3388 | * | ||
3389 | * @param q Handle to the queue. | ||
3390 | */ | ||
3391 | void | ||
3392 | GCC_cancel (struct CadetConnectionQueue *q) | ||
3393 | { | ||
3394 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! GCC cancel message\n"); | ||
3395 | |||
3396 | /* send_cancel calls message_sent, which calls q->cont and frees q */ | ||
3397 | GCP_send_cancel (q->peer_q); | ||
3398 | GCC_check_connections (); | ||
3399 | } | ||
3400 | |||
3401 | |||
3402 | /** | ||
3403 | * Sends a CREATE CONNECTION message for a path to a peer. | ||
3404 | * Changes the connection and tunnel states if necessary. | ||
3405 | * | ||
3406 | * @param c Connection to create. | ||
3407 | */ | ||
3408 | void | ||
3409 | GCC_send_create (struct CadetConnection *c) | ||
3410 | { | ||
3411 | static struct CadetEncryptedMessageIdentifier zero; | ||
3412 | enum CadetTunnelCState state; | ||
3413 | size_t size; | ||
3414 | |||
3415 | GCC_check_connections (); | ||
3416 | size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage); | ||
3417 | size += c->path->length * sizeof (struct GNUNET_PeerIdentity); | ||
3418 | { | ||
3419 | /* Allocate message on the stack */ | ||
3420 | unsigned char cbuf[size]; | ||
3421 | struct GNUNET_CADET_ConnectionCreateMessage *msg; | ||
3422 | struct GNUNET_PeerIdentity *peers; | ||
3423 | |||
3424 | |||
3425 | msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf; | ||
3426 | msg->header.size = htons (size); | ||
3427 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
3428 | msg->reserved = htonl (0); | ||
3429 | msg->cid = *GCC_get_id (c); | ||
3430 | peers = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
3431 | for (int i = 0; i < c->path->length; i++) | ||
3432 | { | 908 | { |
3433 | GNUNET_PEER_resolve (c->path->peers[i], peers++); | 909 | /* keep existing */ |
910 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
911 | "Got two connections on %s, keeping my existing %s\n", | ||
912 | GCPP_2s (path), | ||
913 | GCC_2s (cc)); | ||
914 | return NULL; | ||
3434 | } | 915 | } |
3435 | GNUNET_assert (NULL == c->maintenance_q); | ||
3436 | c->maintenance_q = GCP_send (get_next_hop (c), | ||
3437 | &msg->header, | ||
3438 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
3439 | zero, | ||
3440 | c, GNUNET_YES, | ||
3441 | &conn_message_sent, NULL); | ||
3442 | } | 916 | } |
3443 | 917 | ||
3444 | LOG (GNUNET_ERROR_TYPE_INFO, "==> %s %19s on conn %s (%p) FWD [%5u]\n", | 918 | return connection_create (destination, |
3445 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), "", | 919 | path, |
3446 | GCC_2s (c), c, size); | 920 | off, |
3447 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", | 921 | options, |
3448 | c, c->pending_messages); | 922 | ct, |
3449 | c->pending_messages++; | 923 | cid, |
3450 | 924 | CADET_CONNECTION_CREATE_RECEIVED, | |
3451 | state = GCT_get_cstate (c->t); | 925 | ready_cb, |
3452 | if (CADET_TUNNEL_SEARCHING == state || CADET_TUNNEL_NEW == state) | 926 | ready_cb_cls); |
3453 | GCT_change_cstate (c->t, CADET_TUNNEL_WAITING); | ||
3454 | if (CADET_CONNECTION_NEW == c->state) | ||
3455 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
3456 | GCC_check_connections (); | ||
3457 | } | 927 | } |
3458 | 928 | ||
3459 | 929 | ||
3460 | /** | 930 | /** |
3461 | * Send an ACK on the appropriate connection/channel, depending on | 931 | * Create a connection to @a destination via @a path and |
3462 | * the direction and the position of the peer. | 932 | * notify @a cb whenever we are ready for more data. |
3463 | * | 933 | * |
3464 | * @param c Which connection to send the hop-by-hop ACK. | 934 | * @param destination where to go |
3465 | * @param fwd Is this a fwd ACK? (will go dest->root). | 935 | * @param path which path to take (may not be the full path) |
3466 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | 936 | * @param off offset of @a destination on @a path |
937 | * @param options options for the connection | ||
938 | * @param ct tunnel that uses the connection | ||
939 | * @param ready_cb function to call when ready to transmit | ||
940 | * @param ready_cb_cls closure for @a cb | ||
941 | * @return handle to the connection | ||
3467 | */ | 942 | */ |
3468 | void | 943 | struct CadetConnection * |
3469 | GCC_send_ack (struct CadetConnection *c, int fwd, int force) | 944 | GCC_create (struct CadetPeer *destination, |
945 | struct CadetPeerPath *path, | ||
946 | unsigned int off, | ||
947 | enum GNUNET_CADET_ChannelOption options, | ||
948 | struct CadetTConnection *ct, | ||
949 | GCC_ReadyCallback ready_cb, | ||
950 | void *ready_cb_cls) | ||
3470 | { | 951 | { |
3471 | unsigned int buffer; | 952 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
3472 | |||
3473 | GCC_check_connections (); | ||
3474 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GCC send %s ACK on %s\n", | ||
3475 | GC_f2s (fwd), GCC_2s (c)); | ||
3476 | |||
3477 | if (NULL == c) | ||
3478 | { | ||
3479 | GNUNET_break (0); | ||
3480 | return; | ||
3481 | } | ||
3482 | 953 | ||
3483 | if (GNUNET_NO != c->destroy) | 954 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, |
3484 | { | 955 | &cid, |
3485 | LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); | 956 | sizeof (cid)); |
3486 | GCC_check_connections (); | 957 | return connection_create (destination, |
3487 | return; | 958 | path, |
3488 | } | 959 | off, |
3489 | 960 | options, | |
3490 | /* Get available buffer space */ | 961 | ct, |
3491 | if (GCC_is_terminal (c, fwd)) | 962 | &cid, |
3492 | { | 963 | CADET_CONNECTION_NEW, |
3493 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); | 964 | ready_cb, |
3494 | buffer = GCT_get_channels_buffer (c->t); | 965 | ready_cb_cls); |
3495 | } | ||
3496 | else | ||
3497 | { | ||
3498 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n"); | ||
3499 | buffer = GCC_get_buffer (c, fwd); | ||
3500 | } | ||
3501 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); | ||
3502 | if (0 == buffer && GNUNET_NO == force) | ||
3503 | { | ||
3504 | GCC_check_connections (); | ||
3505 | return; | ||
3506 | } | ||
3507 | |||
3508 | /* Send available buffer space */ | ||
3509 | if (GNUNET_YES == GCC_is_origin (c, fwd)) | ||
3510 | { | ||
3511 | GNUNET_assert (NULL != c->t); | ||
3512 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n"); | ||
3513 | GCT_unchoke_channels (c->t); | ||
3514 | } | ||
3515 | else | ||
3516 | { | ||
3517 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); | ||
3518 | send_ack (c, buffer, fwd, force); | ||
3519 | } | ||
3520 | GCC_check_connections (); | ||
3521 | } | 966 | } |
3522 | 967 | ||
3523 | 968 | ||
3524 | /** | 969 | /** |
3525 | * Send a message to all peers in this connection that the connection | 970 | * Transmit message @a msg via connection @a cc. Must only be called |
3526 | * is no longer valid. | 971 | * (once) after the connection has signalled that it is ready via the |
972 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
973 | * connection is right now ready for transmission. | ||
3527 | * | 974 | * |
3528 | * If some peer should not receive the message, it should be zero'ed out | 975 | * @param cc connection identification |
3529 | * before calling this function. | 976 | * @param env envelope with message to transmit; must NOT |
3530 | * | 977 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it |
3531 | * @param c The connection whose peers to notify. | ||
3532 | */ | 978 | */ |
3533 | void | 979 | void |
3534 | GCC_send_destroy (struct CadetConnection *c) | 980 | GCC_transmit (struct CadetConnection *cc, |
981 | struct GNUNET_MQ_Envelope *env) | ||
3535 | { | 982 | { |
3536 | static struct CadetEncryptedMessageIdentifier zero; | ||
3537 | struct GNUNET_CADET_ConnectionDestroyMessage msg; | ||
3538 | |||
3539 | if (GNUNET_YES == c->destroy) | ||
3540 | return; | ||
3541 | GCC_check_connections (); | ||
3542 | msg.header.size = htons (sizeof (msg)); | ||
3543 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
3544 | msg.cid = c->id; | ||
3545 | msg.reserved = htonl (0); | ||
3546 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 983 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3547 | " sending connection destroy for connection %s\n", | 984 | "Scheduling message for transmission on %s\n", |
3548 | GCC_2s (c)); | 985 | GCC_2s (cc)); |
3549 | 986 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | |
3550 | if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES)) | 987 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); |
3551 | (void) GCC_send_prebuilt_message (&msg.header, | 988 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); |
3552 | UINT16_MAX, | 989 | cc->mqm_ready = GNUNET_NO; |
3553 | zero, | 990 | if (NULL != cc->task) |
3554 | c, | 991 | { |
3555 | GNUNET_YES, GNUNET_YES, NULL, NULL); | 992 | GNUNET_SCHEDULER_cancel (cc->task); |
3556 | if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO)) | 993 | cc->task = NULL; |
3557 | (void) GCC_send_prebuilt_message (&msg.header, | 994 | } |
3558 | UINT16_MAX, | 995 | GCP_send (cc->mq_man, |
3559 | zero, | 996 | env); |
3560 | c, | ||
3561 | GNUNET_NO, GNUNET_YES, NULL, NULL); | ||
3562 | mark_destroyed (c); | ||
3563 | GCC_check_connections (); | ||
3564 | } | 997 | } |
3565 | 998 | ||
3566 | 999 | ||
3567 | /** | 1000 | /** |
3568 | * @brief Start a polling timer for the connection. | 1001 | * Obtain the path used by this connection. |
3569 | * | ||
3570 | * When a neighbor does not accept more traffic on the connection it could be | ||
3571 | * caused by a simple congestion or by a lost ACK. Polling enables to check | ||
3572 | * for the lastest ACK status for a connection. | ||
3573 | * | 1002 | * |
3574 | * @param c Connection. | 1003 | * @param cc connection |
3575 | * @param fwd Should we poll in the FWD direction? | 1004 | * @return path to @a cc |
3576 | */ | 1005 | */ |
3577 | void | 1006 | struct CadetPeerPath * |
3578 | GCC_start_poll (struct CadetConnection *c, int fwd) | 1007 | GCC_get_path (struct CadetConnection *cc) |
3579 | { | 1008 | { |
3580 | struct CadetFlowControl *fc; | 1009 | return cc->path; |
3581 | |||
3582 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3583 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL %s requested\n", | ||
3584 | GC_f2s (fwd)); | ||
3585 | if (NULL != fc->poll_task || NULL != fc->poll_msg) | ||
3586 | { | ||
3587 | LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL already in progress (t: %p, m: %p)\n", | ||
3588 | fc->poll_task, fc->poll_msg); | ||
3589 | return; | ||
3590 | } | ||
3591 | if (0 == fc->queue_max) | ||
3592 | { | ||
3593 | /* Should not be needed, traffic should've been cancelled. */ | ||
3594 | GNUNET_break (0); | ||
3595 | LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL not possible, peer disconnected\n"); | ||
3596 | return; | ||
3597 | } | ||
3598 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL started on request\n"); | ||
3599 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &send_poll, fc); | ||
3600 | } | 1010 | } |
3601 | 1011 | ||
3602 | 1012 | ||
3603 | /** | 1013 | /** |
3604 | * @brief Stop polling a connection for ACKs. | 1014 | * Obtain unique ID for the connection. |
3605 | * | 1015 | * |
3606 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | 1016 | * @param cc connection. |
3607 | * | 1017 | * @return unique number of the connection |
3608 | * @param c Connection. | ||
3609 | * @param fwd Should we stop the poll in the FWD direction? | ||
3610 | */ | 1018 | */ |
3611 | void | 1019 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
3612 | GCC_stop_poll (struct CadetConnection *c, int fwd) | 1020 | GCC_get_id (struct CadetConnection *cc) |
3613 | { | 1021 | { |
3614 | struct CadetFlowControl *fc; | 1022 | return &cc->cid; |
3615 | |||
3616 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3617 | if (NULL != fc->poll_task) | ||
3618 | { | ||
3619 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
3620 | fc->poll_task = NULL; | ||
3621 | } | ||
3622 | if (NULL != fc->poll_msg) | ||
3623 | { | ||
3624 | GCC_cancel (fc->poll_msg); | ||
3625 | fc->poll_msg = NULL; | ||
3626 | } | ||
3627 | } | 1023 | } |
3628 | 1024 | ||
3629 | 1025 | ||
3630 | /** | 1026 | /** |
3631 | * Get a (static) string for a connection. | 1027 | * Get a (static) string for a connection. |
3632 | * | 1028 | * |
3633 | * @param c Connection. | 1029 | * @param cc Connection. |
3634 | */ | 1030 | */ |
3635 | const char * | 1031 | const char * |
3636 | GCC_2s (const struct CadetConnection *c) | 1032 | GCC_2s (const struct CadetConnection *cc) |
3637 | { | 1033 | { |
3638 | if (NULL == c) | 1034 | static char buf[128]; |
3639 | return "NULL"; | ||
3640 | 1035 | ||
3641 | if (NULL != c->t) | 1036 | if (NULL == cc) |
3642 | { | 1037 | return "Connection(NULL)"; |
3643 | static char buf[128]; | ||
3644 | 1038 | ||
3645 | SPRINTF (buf, "%s (->%s)", | 1039 | if (NULL != cc->ct) |
3646 | GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel), | 1040 | { |
3647 | GCT_2s (c->t)); | 1041 | GNUNET_snprintf (buf, |
1042 | sizeof (buf), | ||
1043 | "Connection %s (%s)", | ||
1044 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
1045 | GCT_2s (cc->ct->t)); | ||
3648 | return buf; | 1046 | return buf; |
3649 | } | 1047 | } |
3650 | return GNUNET_sh2s (&c->id.connection_of_tunnel); | 1048 | GNUNET_snprintf (buf, |
1049 | sizeof (buf), | ||
1050 | "Connection %s", | ||
1051 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
1052 | return buf; | ||
3651 | } | 1053 | } |
3652 | 1054 | ||
3653 | 1055 | ||
1056 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
1057 | |||
1058 | |||
3654 | /** | 1059 | /** |
3655 | * Log all possible info about the connection state. | 1060 | * Log connection info. |
3656 | * | 1061 | * |
3657 | * @param c Connection to debug. | 1062 | * @param cc connection |
3658 | * @param level Debug level to use. | 1063 | * @param level Debug level to use. |
3659 | */ | 1064 | */ |
3660 | void | 1065 | void |
3661 | GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level) | 1066 | GCC_debug (struct CadetConnection *cc, |
1067 | enum GNUNET_ErrorType level) | ||
3662 | { | 1068 | { |
3663 | int do_log; | 1069 | int do_log; |
3664 | char *s; | ||
3665 | 1070 | ||
3666 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | 1071 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), |
3667 | "cadet-con", | 1072 | "cadet-con", |
3668 | __FILE__, __FUNCTION__, __LINE__); | 1073 | __FILE__, __FUNCTION__, __LINE__); |
3669 | if (0 == do_log) | 1074 | if (0 == do_log) |
3670 | return; | 1075 | return; |
3671 | 1076 | if (NULL == cc) | |
3672 | if (NULL == c) | ||
3673 | { | 1077 | { |
3674 | LOG2 (level, "CCC DEBUG NULL CONNECTION\n"); | 1078 | LOG2 (level, |
1079 | "Connection (NULL)\n"); | ||
3675 | return; | 1080 | return; |
3676 | } | 1081 | } |
3677 | 1082 | LOG2 (level, | |
3678 | LOG2 (level, "CCC DEBUG CONNECTION %s\n", GCC_2s (c)); | 1083 | "%s to %s via path %s in state %d is %s\n", |
3679 | s = path_2s (c->path); | 1084 | GCC_2s (cc), |
3680 | LOG2 (level, "CCC path %s, own pos: %u\n", s, c->own_pos); | 1085 | GCP_2s (cc->destination), |
3681 | GNUNET_free (s); | 1086 | GCPP_2s (cc->path), |
3682 | LOG2 (level, "CCC state: %s, destroy: %u\n", | 1087 | cc->state, |
3683 | GCC_state2s (c->state), c->destroy); | 1088 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); |
3684 | LOG2 (level, "CCC pending messages: %u\n", c->pending_messages); | ||
3685 | if (NULL != c->perf) | ||
3686 | LOG2 (level, "CCC us/byte: %f\n", c->perf->avg); | ||
3687 | |||
3688 | LOG2 (level, "CCC FWD flow control:\n"); | ||
3689 | LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max); | ||
3690 | LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", | ||
3691 | ntohl (c->fwd_fc.last_pid_sent.pid), | ||
3692 | ntohl (c->fwd_fc.last_pid_recv.pid)); | ||
3693 | LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", | ||
3694 | ntohl (c->fwd_fc.last_ack_sent.pid), | ||
3695 | ntohl (c->fwd_fc.last_ack_recv.pid)); | ||
3696 | LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap); | ||
3697 | LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", | ||
3698 | c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg); | ||
3699 | |||
3700 | LOG2 (level, "CCC BCK flow control:\n"); | ||
3701 | LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max); | ||
3702 | LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", | ||
3703 | ntohl (c->bck_fc.last_pid_sent.pid), | ||
3704 | ntohl (c->bck_fc.last_pid_recv.pid)); | ||
3705 | LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", | ||
3706 | ntohl (c->bck_fc.last_ack_sent.pid), | ||
3707 | ntohl (c->bck_fc.last_ack_recv.pid)); | ||
3708 | LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap); | ||
3709 | LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", | ||
3710 | c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg); | ||
3711 | |||
3712 | LOG2 (level, "CCC DEBUG CONNECTION END\n"); | ||
3713 | } | 1089 | } |
1090 | |||
1091 | /* end of gnunet-service-cadet-new_connection.c */ | ||