diff options
Diffstat (limited to 'src/service/cadet/gnunet-service-cadet_channel.c')
-rw-r--r-- | src/service/cadet/gnunet-service-cadet_channel.c | 2008 |
1 files changed, 2008 insertions, 0 deletions
diff --git a/src/service/cadet/gnunet-service-cadet_channel.c b/src/service/cadet/gnunet-service-cadet_channel.c new file mode 100644 index 000000000..78658c296 --- /dev/null +++ b/src/service/cadet/gnunet-service-cadet_channel.c | |||
@@ -0,0 +1,2008 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_channel.c | ||
22 | * @brief logical links between CADET clients | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - Congestion/flow control: | ||
28 | * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
29 | * (and figure out how/where to use this!) | ||
30 | * + figure out flow control without ACKs (unreliable traffic!) | ||
31 | * - revisit handling of 'unbuffered' traffic! | ||
32 | * (need to push down through tunnel into connection selection) | ||
33 | * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe | ||
34 | * reserve more bits in 'options' to allow for buffer size control? | ||
35 | */ | ||
36 | #include "platform.h" | ||
37 | #include "cadet.h" | ||
38 | #include "gnunet_statistics_service.h" | ||
39 | #include "gnunet-service-cadet_channel.h" | ||
40 | #include "gnunet-service-cadet_connection.h" | ||
41 | #include "gnunet-service-cadet_tunnels.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
43 | |||
44 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__) | ||
45 | |||
46 | /** | ||
47 | * How long do we initially wait before retransmitting? | ||
48 | */ | ||
49 | #define CADET_INITIAL_RETRANSMIT_TIME \ | ||
50 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
51 | |||
52 | /** | ||
53 | * How long do we wait before dropping state about incoming | ||
54 | * connection to closed port? | ||
55 | */ | ||
56 | #define TIMEOUT_CLOSED_PORT \ | ||
57 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
58 | |||
59 | /** | ||
60 | * How long do we wait at least before retransmitting ever? | ||
61 | */ | ||
62 | #define MIN_RTT_DELAY \ | ||
63 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75) | ||
64 | |||
65 | /** | ||
66 | * Maximum message ID into the future we accept for out-of-order messages. | ||
67 | * If the message is more than this into the future, we drop it. This is | ||
68 | * important both to detect values that are actually in the past, as well | ||
69 | * as to limit adversarially triggerable memory consumption. | ||
70 | * | ||
71 | * Note that right now we have "max_pending_messages = 4" hard-coded in | ||
72 | * the logic below, so a value of 4 would suffice here. But we plan to | ||
73 | * allow larger windows in the future... | ||
74 | */ | ||
75 | #define MAX_OUT_OF_ORDER_DISTANCE 1024 | ||
76 | |||
77 | |||
78 | /** | ||
79 | * All the states a channel can be in. | ||
80 | */ | ||
81 | enum CadetChannelState | ||
82 | { | ||
83 | /** | ||
84 | * Uninitialized status, should never appear in operation. | ||
85 | */ | ||
86 | CADET_CHANNEL_NEW, | ||
87 | |||
88 | /** | ||
89 | * Channel is to a port that is not open, we're waiting for the | ||
90 | * port to be opened. | ||
91 | */ | ||
92 | CADET_CHANNEL_LOOSE, | ||
93 | |||
94 | /** | ||
95 | * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK. | ||
96 | */ | ||
97 | CADET_CHANNEL_OPEN_SENT, | ||
98 | |||
99 | /** | ||
100 | * Connection confirmed, ready to carry traffic. | ||
101 | */ | ||
102 | CADET_CHANNEL_READY | ||
103 | }; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Info needed to retry a message in case it gets lost. | ||
108 | * Note that we DO use this structure also for unreliable | ||
109 | * messages. | ||
110 | */ | ||
111 | struct CadetReliableMessage | ||
112 | { | ||
113 | /** | ||
114 | * Double linked list, FIFO style | ||
115 | */ | ||
116 | struct CadetReliableMessage *next; | ||
117 | |||
118 | /** | ||
119 | * Double linked list, FIFO style | ||
120 | */ | ||
121 | struct CadetReliableMessage *prev; | ||
122 | |||
123 | /** | ||
124 | * Which channel is this message in? | ||
125 | */ | ||
126 | struct CadetChannel *ch; | ||
127 | |||
128 | /** | ||
129 | * Entry in the tunnels queue for this message, NULL if it has left | ||
130 | * the tunnel. Used to cancel transmission in case we receive an | ||
131 | * ACK in time. | ||
132 | */ | ||
133 | struct CadetTunnelQueueEntry *qe; | ||
134 | |||
135 | /** | ||
136 | * Data message we are trying to send. | ||
137 | */ | ||
138 | struct GNUNET_CADET_ChannelAppDataMessage *data_message; | ||
139 | |||
140 | /** | ||
141 | * How soon should we retry if we fail to get an ACK? | ||
142 | * Messages in the queue are sorted by this value. | ||
143 | */ | ||
144 | struct GNUNET_TIME_Absolute next_retry; | ||
145 | |||
146 | /** | ||
147 | * How long do we wait for an ACK after transmission? | ||
148 | * Use for the back-off calculation. | ||
149 | */ | ||
150 | struct GNUNET_TIME_Relative retry_delay; | ||
151 | |||
152 | /** | ||
153 | * Time when we first successfully transmitted the message | ||
154 | * (that is, set @e num_transmissions to 1). | ||
155 | */ | ||
156 | struct GNUNET_TIME_Absolute first_transmission_time; | ||
157 | |||
158 | /** | ||
159 | * Identifier of the connection that this message took when it | ||
160 | * was first transmitted. Only useful if @e num_transmissions is 1. | ||
161 | */ | ||
162 | struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken; | ||
163 | |||
164 | /** | ||
165 | * How often was this message transmitted? #GNUNET_SYSERR if there | ||
166 | * was an error transmitting the message, #GNUNET_NO if it was not | ||
167 | * yet transmitted ever, otherwise the number of (re) transmissions. | ||
168 | */ | ||
169 | int num_transmissions; | ||
170 | }; | ||
171 | |||
172 | |||
173 | /** | ||
174 | * List of received out-of-order data messages. | ||
175 | */ | ||
176 | struct CadetOutOfOrderMessage | ||
177 | { | ||
178 | /** | ||
179 | * Double linked list, FIFO style | ||
180 | */ | ||
181 | struct CadetOutOfOrderMessage *next; | ||
182 | |||
183 | /** | ||
184 | * Double linked list, FIFO style | ||
185 | */ | ||
186 | struct CadetOutOfOrderMessage *prev; | ||
187 | |||
188 | /** | ||
189 | * ID of the message (messages up to this point needed | ||
190 | * before we give this one to the client). | ||
191 | */ | ||
192 | struct ChannelMessageIdentifier mid; | ||
193 | |||
194 | /** | ||
195 | * The envelope with the payload of the out-of-order message | ||
196 | */ | ||
197 | struct GNUNET_MQ_Envelope *env; | ||
198 | }; | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Client endpoint of a `struct CadetChannel`. A channel may be a | ||
203 | * loopback channel, in which case it has two of these endpoints. | ||
204 | * Note that flow control also is required in both directions. | ||
205 | */ | ||
206 | struct CadetChannelClient | ||
207 | { | ||
208 | /** | ||
209 | * Client handle. Not by itself sufficient to designate | ||
210 | * the client endpoint, as the same client handle may | ||
211 | * be used for both the owner and the destination, and | ||
212 | * we thus also need the channel ID to identify the client. | ||
213 | */ | ||
214 | struct CadetClient *c; | ||
215 | |||
216 | /** | ||
217 | * Head of DLL of messages received out of order or while client was unready. | ||
218 | */ | ||
219 | struct CadetOutOfOrderMessage *head_recv; | ||
220 | |||
221 | /** | ||
222 | * Tail DLL of messages received out of order or while client was unready. | ||
223 | */ | ||
224 | struct CadetOutOfOrderMessage *tail_recv; | ||
225 | |||
226 | /** | ||
227 | * Local tunnel number for this client. | ||
228 | * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI, | ||
229 | * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
230 | */ | ||
231 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
232 | |||
233 | /** | ||
234 | * Number of entries currently in @a head_recv DLL. | ||
235 | */ | ||
236 | unsigned int num_recv; | ||
237 | |||
238 | /** | ||
239 | * Can we send data to the client? | ||
240 | */ | ||
241 | int client_ready; | ||
242 | }; | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Struct containing all information regarding a channel to a remote client. | ||
247 | */ | ||
248 | struct CadetChannel | ||
249 | { | ||
250 | /** | ||
251 | * Tunnel this channel is in. | ||
252 | */ | ||
253 | struct CadetTunnel *t; | ||
254 | |||
255 | /** | ||
256 | * Client owner of the tunnel, if any. | ||
257 | * (Used if this channel represends the initiating end of the tunnel.) | ||
258 | */ | ||
259 | struct CadetChannelClient *owner; | ||
260 | |||
261 | /** | ||
262 | * Client destination of the tunnel, if any. | ||
263 | * (Used if this channel represents the listening end of the tunnel.) | ||
264 | */ | ||
265 | struct CadetChannelClient *dest; | ||
266 | |||
267 | /** | ||
268 | * Last entry in the tunnel's queue relating to control messages | ||
269 | * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or | ||
270 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel | ||
271 | * transmission in case we receive updated information. | ||
272 | */ | ||
273 | struct CadetTunnelQueueEntry *last_control_qe; | ||
274 | |||
275 | /** | ||
276 | * Head of DLL of messages sent and not yet ACK'd. | ||
277 | */ | ||
278 | struct CadetReliableMessage *head_sent; | ||
279 | |||
280 | /** | ||
281 | * Tail of DLL of messages sent and not yet ACK'd. | ||
282 | */ | ||
283 | struct CadetReliableMessage *tail_sent; | ||
284 | |||
285 | /** | ||
286 | * Task to resend/poll in case no ACK is received. | ||
287 | */ | ||
288 | struct GNUNET_SCHEDULER_Task *retry_control_task; | ||
289 | |||
290 | /** | ||
291 | * Task to resend/poll in case no ACK is received. | ||
292 | */ | ||
293 | struct GNUNET_SCHEDULER_Task *retry_data_task; | ||
294 | |||
295 | /** | ||
296 | * Last time the channel was used | ||
297 | */ | ||
298 | struct GNUNET_TIME_Absolute timestamp; | ||
299 | |||
300 | /** | ||
301 | * Destination port of the channel. | ||
302 | */ | ||
303 | struct GNUNET_HashCode port; | ||
304 | |||
305 | /** | ||
306 | * Hash'ed port of the channel with initiator and destination PID. | ||
307 | */ | ||
308 | struct GNUNET_HashCode h_port; | ||
309 | |||
310 | /** | ||
311 | * Counter for exponential backoff. | ||
312 | */ | ||
313 | struct GNUNET_TIME_Relative retry_time; | ||
314 | |||
315 | /** | ||
316 | * Bitfield of already-received messages past @e mid_recv. | ||
317 | */ | ||
318 | uint64_t mid_futures; | ||
319 | |||
320 | /** | ||
321 | * Next MID expected for incoming traffic. | ||
322 | */ | ||
323 | struct ChannelMessageIdentifier mid_recv; | ||
324 | |||
325 | /** | ||
326 | * Next MID to use for outgoing traffic. | ||
327 | */ | ||
328 | struct ChannelMessageIdentifier mid_send; | ||
329 | |||
330 | /** | ||
331 | * Total (reliable) messages pending ACK for this channel. | ||
332 | */ | ||
333 | unsigned int pending_messages; | ||
334 | |||
335 | /** | ||
336 | * Maximum (reliable) messages pending ACK for this channel | ||
337 | * before we throttle the client. | ||
338 | */ | ||
339 | unsigned int max_pending_messages; | ||
340 | |||
341 | /** | ||
342 | * Number identifying this channel in its tunnel. | ||
343 | */ | ||
344 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
345 | |||
346 | /** | ||
347 | * Channel state. | ||
348 | */ | ||
349 | enum CadetChannelState state; | ||
350 | |||
351 | /** | ||
352 | * Count how many ACKs we skipped, used to prevent long | ||
353 | * sequences of ACK skipping. | ||
354 | */ | ||
355 | unsigned int skip_ack_series; | ||
356 | |||
357 | /** | ||
358 | * Is the tunnel bufferless (minimum latency)? | ||
359 | */ | ||
360 | int nobuffer; | ||
361 | |||
362 | /** | ||
363 | * Is the tunnel reliable? | ||
364 | */ | ||
365 | int reliable; | ||
366 | |||
367 | /** | ||
368 | * Is the tunnel out-of-order? | ||
369 | */ | ||
370 | int out_of_order; | ||
371 | |||
372 | /** | ||
373 | * Is this channel a loopback channel, where the destination is us again? | ||
374 | */ | ||
375 | int is_loopback; | ||
376 | |||
377 | /** | ||
378 | * Flag to signal the destruction of the channel. If this is set to | ||
379 | * #GNUNET_YES the channel will be destroyed once the queue is | ||
380 | * empty. | ||
381 | */ | ||
382 | int destroy; | ||
383 | |||
384 | /** | ||
385 | * Type of message to be dropped. See GCT_send. | ||
386 | */ | ||
387 | uint16_t type GNUNET_PACKED; | ||
388 | |||
389 | }; | ||
390 | |||
391 | void | ||
392 | GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct | ||
393 | GNUNET_CADET_RequestDropCadetMessage *message) | ||
394 | { | ||
395 | |||
396 | ch->type = message->type; | ||
397 | |||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Check if type of message is the one to drop. | ||
403 | * @param ch CadetChannel to check for message type to drop. | ||
404 | * @param message GNUNET_MessageHeader to compare the type with. | ||
405 | */ | ||
406 | int | ||
407 | GCCH_is_type_to_drop (struct CadetChannel *ch, const struct | ||
408 | GNUNET_MessageHeader *message) | ||
409 | { | ||
410 | |||
411 | if (ch->type == message->type) | ||
412 | { | ||
413 | ch->type = 0; | ||
414 | return GNUNET_YES; | ||
415 | } | ||
416 | else | ||
417 | return GNUNET_NO; | ||
418 | } | ||
419 | |||
420 | |||
421 | /** | ||
422 | * Get the static string for identification of the channel. | ||
423 | * | ||
424 | * @param ch Channel. | ||
425 | * | ||
426 | * @return Static string with the channel IDs. | ||
427 | */ | ||
428 | const char * | ||
429 | GCCH_2s (const struct CadetChannel *ch) | ||
430 | { | ||
431 | static char buf[128]; | ||
432 | |||
433 | GNUNET_snprintf (buf, | ||
434 | sizeof(buf), | ||
435 | "Channel %s:%s ctn:%X(%X/%X)", | ||
436 | (GNUNET_YES == ch->is_loopback) | ||
437 | ? "loopback" | ||
438 | : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))), | ||
439 | GNUNET_h2s (&ch->port), | ||
440 | ch->ctn.cn, | ||
441 | (NULL == ch->owner) | ||
442 | ? 0 | ||
443 | : ntohl (ch->owner->ccn.channel_of_client), | ||
444 | (NULL == ch->dest) | ||
445 | ? 0 | ||
446 | : ntohl (ch->dest->ccn.channel_of_client)); | ||
447 | return buf; | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * Hash the @a port and @a initiator and @a listener to | ||
453 | * calculate the "challenge" @a h_port we send to the other | ||
454 | * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN. | ||
455 | * | ||
456 | * @param[out] h_port set to the hash of @a port, @a initiator and @a listener | ||
457 | * @param port cadet port, as seen by CADET clients | ||
458 | * @param listener peer that is listining on @a port | ||
459 | */ | ||
460 | void | ||
461 | GCCH_hash_port (struct GNUNET_HashCode *h_port, | ||
462 | const struct GNUNET_HashCode *port, | ||
463 | const struct GNUNET_PeerIdentity *listener) | ||
464 | { | ||
465 | struct GNUNET_HashContext *hc; | ||
466 | |||
467 | hc = GNUNET_CRYPTO_hash_context_start (); | ||
468 | GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port)); | ||
469 | GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener)); | ||
470 | GNUNET_CRYPTO_hash_context_finish (hc, h_port); | ||
471 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
472 | "Calculated port hash %s\n", | ||
473 | GNUNET_h2s (h_port)); | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * Get the channel's public ID. | ||
479 | * | ||
480 | * @param ch Channel. | ||
481 | * | ||
482 | * @return ID used to identify the channel with the remote peer. | ||
483 | */ | ||
484 | struct GNUNET_CADET_ChannelTunnelNumber | ||
485 | GCCH_get_id (const struct CadetChannel *ch) | ||
486 | { | ||
487 | return ch->ctn; | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Release memory associated with @a ccc | ||
493 | * | ||
494 | * @param ccc data structure to clean up | ||
495 | */ | ||
496 | static void | ||
497 | free_channel_client (struct CadetChannelClient *ccc) | ||
498 | { | ||
499 | struct CadetOutOfOrderMessage *com; | ||
500 | |||
501 | while (NULL != (com = ccc->head_recv)) | ||
502 | { | ||
503 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
504 | ccc->num_recv--; | ||
505 | GNUNET_MQ_discard (com->env); | ||
506 | GNUNET_free (com); | ||
507 | } | ||
508 | GNUNET_free (ccc); | ||
509 | } | ||
510 | |||
511 | |||
512 | /** | ||
513 | * Destroy the given channel. | ||
514 | * | ||
515 | * @param ch channel to destroy | ||
516 | */ | ||
517 | static void | ||
518 | channel_destroy (struct CadetChannel *ch) | ||
519 | { | ||
520 | struct CadetReliableMessage *crm; | ||
521 | |||
522 | while (NULL != (crm = ch->head_sent)) | ||
523 | { | ||
524 | GNUNET_assert (ch == crm->ch); | ||
525 | if (NULL != crm->qe) | ||
526 | { | ||
527 | GCT_send_cancel (crm->qe); | ||
528 | crm->qe = NULL; | ||
529 | } | ||
530 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
531 | GNUNET_free (crm->data_message); | ||
532 | GNUNET_free (crm); | ||
533 | } | ||
534 | if (CADET_CHANNEL_LOOSE == ch->state) | ||
535 | { | ||
536 | GSC_drop_loose_channel (&ch->h_port, ch); | ||
537 | } | ||
538 | if (NULL != ch->owner) | ||
539 | { | ||
540 | free_channel_client (ch->owner); | ||
541 | ch->owner = NULL; | ||
542 | } | ||
543 | if (NULL != ch->dest) | ||
544 | { | ||
545 | free_channel_client (ch->dest); | ||
546 | ch->dest = NULL; | ||
547 | } | ||
548 | if (NULL != ch->last_control_qe) | ||
549 | { | ||
550 | GCT_send_cancel (ch->last_control_qe); | ||
551 | ch->last_control_qe = NULL; | ||
552 | } | ||
553 | if (NULL != ch->retry_data_task) | ||
554 | { | ||
555 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
556 | ch->retry_data_task = NULL; | ||
557 | } | ||
558 | if (NULL != ch->retry_control_task) | ||
559 | { | ||
560 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
561 | ch->retry_control_task = NULL; | ||
562 | } | ||
563 | if (GNUNET_NO == ch->is_loopback) | ||
564 | { | ||
565 | GCT_remove_channel (ch->t, ch, ch->ctn); | ||
566 | ch->t = NULL; | ||
567 | } | ||
568 | GNUNET_free (ch); | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Send a channel create message. | ||
574 | * | ||
575 | * @param cls Channel for which to send. | ||
576 | */ | ||
577 | static void | ||
578 | send_channel_open (void *cls); | ||
579 | |||
580 | |||
581 | /** | ||
582 | * Function called once the tunnel confirms that we sent the | ||
583 | * create message. Delays for a bit until we retry. | ||
584 | * | ||
585 | * @param cls our `struct CadetChannel`. | ||
586 | * @param cid identifier of the connection within the tunnel, NULL | ||
587 | * if transmission failed | ||
588 | */ | ||
589 | static void | ||
590 | channel_open_sent_cb (void *cls, | ||
591 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
592 | { | ||
593 | struct CadetChannel *ch = cls; | ||
594 | |||
595 | GNUNET_assert (NULL != ch->last_control_qe); | ||
596 | ch->last_control_qe = NULL; | ||
597 | ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time); | ||
598 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
599 | "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n", | ||
600 | GCCH_2s (ch), | ||
601 | GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES)); | ||
602 | ch->retry_control_task = | ||
603 | GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch); | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Send a channel open message. | ||
609 | * | ||
610 | * @param cls Channel for which to send. | ||
611 | */ | ||
612 | static void | ||
613 | send_channel_open (void *cls) | ||
614 | { | ||
615 | struct CadetChannel *ch = cls; | ||
616 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | ||
617 | |||
618 | ch->retry_control_task = NULL; | ||
619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | "Sending CHANNEL_OPEN message for %s\n", | ||
621 | GCCH_2s (ch)); | ||
622 | msgcc.header.size = htons (sizeof(msgcc)); | ||
623 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | ||
624 | // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed. | ||
625 | msgcc.opt = 2; | ||
626 | msgcc.h_port = ch->h_port; | ||
627 | msgcc.ctn = ch->ctn; | ||
628 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
629 | if (NULL != ch->last_control_qe) | ||
630 | GCT_send_cancel (ch->last_control_qe); | ||
631 | ch->last_control_qe = | ||
632 | GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn); | ||
633 | GNUNET_assert (NULL == ch->retry_control_task); | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Function called once and only once after a channel was bound | ||
639 | * to its tunnel via #GCT_add_channel() is ready for transmission. | ||
640 | * Note that this is only the case for channels that this peer | ||
641 | * initiates, as for incoming channels we assume that they are | ||
642 | * ready for transmission immediately upon receiving the open | ||
643 | * message. Used to bootstrap the #GCT_send() process. | ||
644 | * | ||
645 | * @param ch the channel for which the tunnel is now ready | ||
646 | */ | ||
647 | void | ||
648 | GCCH_tunnel_up (struct CadetChannel *ch) | ||
649 | { | ||
650 | GNUNET_assert (NULL == ch->retry_control_task); | ||
651 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
652 | "Tunnel up, sending CHANNEL_OPEN on %s now\n", | ||
653 | GCCH_2s (ch)); | ||
654 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch); | ||
655 | } | ||
656 | |||
657 | |||
658 | struct CadetChannel * | ||
659 | GCCH_channel_local_new (struct CadetClient *owner, | ||
660 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
661 | struct CadetPeer *destination, | ||
662 | const struct GNUNET_HashCode *port, | ||
663 | uint32_t options) | ||
664 | { | ||
665 | struct CadetChannel *ch; | ||
666 | struct CadetChannelClient *ccco; | ||
667 | |||
668 | ccco = GNUNET_new (struct CadetChannelClient); | ||
669 | ccco->c = owner; | ||
670 | ccco->ccn = ccn; | ||
671 | ccco->client_ready = GNUNET_YES; | ||
672 | |||
673 | ch = GNUNET_new (struct CadetChannel); | ||
674 | ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */ | ||
675 | ch->nobuffer = GNUNET_NO; | ||
676 | ch->reliable = GNUNET_YES; | ||
677 | ch->out_of_order = GNUNET_NO; | ||
678 | ch->max_pending_messages = | ||
679 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
680 | ch->owner = ccco; | ||
681 | ch->port = *port; | ||
682 | GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination)); | ||
683 | if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination))) | ||
684 | { | ||
685 | struct OpenPort *op; | ||
686 | |||
687 | ch->is_loopback = GNUNET_YES; | ||
688 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port); | ||
689 | if (NULL == op) | ||
690 | { | ||
691 | /* port closed, wait for it to possibly open */ | ||
692 | ch->state = CADET_CHANNEL_LOOSE; | ||
693 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
694 | loose_channels, | ||
695 | &ch->h_port, | ||
696 | ch, | ||
697 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
698 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
699 | "Created loose incoming loopback channel to port %s\n", | ||
700 | GNUNET_h2s (&ch->port)); | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | GCCH_bind (ch, op->c, &op->port); | ||
705 | } | ||
706 | } | ||
707 | else | ||
708 | { | ||
709 | ch->t = GCP_get_tunnel (destination, GNUNET_YES); | ||
710 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
711 | ch->ctn = GCT_add_channel (ch->t, ch); | ||
712 | } | ||
713 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
715 | "Created channel to port %s at peer %s for %s using %s\n", | ||
716 | GNUNET_h2s (port), | ||
717 | GCP_2s (destination), | ||
718 | GSC_2s (owner), | ||
719 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); | ||
720 | return ch; | ||
721 | } | ||
722 | |||
723 | |||
724 | /** | ||
725 | * We had an incoming channel to a port that is closed. | ||
726 | * It has not been opened for a while, drop it. | ||
727 | * | ||
728 | * @param cls the channel to drop | ||
729 | */ | ||
730 | static void | ||
731 | timeout_closed_cb (void *cls) | ||
732 | { | ||
733 | struct CadetChannel *ch = cls; | ||
734 | |||
735 | ch->retry_control_task = NULL; | ||
736 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
737 | "Closing incoming channel to port %s from peer %s due to timeout\n", | ||
738 | GNUNET_h2s (&ch->port), | ||
739 | GCP_2s (GCT_get_destination (ch->t))); | ||
740 | channel_destroy (ch); | ||
741 | } | ||
742 | |||
743 | |||
744 | struct CadetChannel * | ||
745 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
746 | struct GNUNET_CADET_ChannelTunnelNumber ctn, | ||
747 | const struct GNUNET_HashCode *h_port, | ||
748 | uint32_t options) | ||
749 | { | ||
750 | struct CadetChannel *ch; | ||
751 | struct OpenPort *op; | ||
752 | |||
753 | ch = GNUNET_new (struct CadetChannel); | ||
754 | ch->h_port = *h_port; | ||
755 | ch->t = t; | ||
756 | ch->ctn = ctn; | ||
757 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
758 | ch->nobuffer = GNUNET_NO; | ||
759 | ch->reliable = GNUNET_YES; | ||
760 | ch->out_of_order = GNUNET_NO; | ||
761 | ch->max_pending_messages = | ||
762 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
763 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
764 | |||
765 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port); | ||
766 | if (NULL == op) | ||
767 | { | ||
768 | /* port closed, wait for it to possibly open */ | ||
769 | ch->state = CADET_CHANNEL_LOOSE; | ||
770 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
771 | loose_channels, | ||
772 | &ch->h_port, | ||
773 | ch, | ||
774 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
775 | GNUNET_assert (NULL == ch->retry_control_task); | ||
776 | ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT, | ||
777 | &timeout_closed_cb, | ||
778 | ch); | ||
779 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
780 | "Created loose incoming channel to port %s from peer %s\n", | ||
781 | GNUNET_h2s (&ch->port), | ||
782 | GCP_2s (GCT_get_destination (ch->t))); | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | GCCH_bind (ch, op->c, &op->port); | ||
787 | } | ||
788 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
789 | return ch; | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Function called once the tunnel confirms that we sent the | ||
795 | * ACK message. Just remembers it was sent, we do not expect | ||
796 | * ACKs for ACKs ;-). | ||
797 | * | ||
798 | * @param cls our `struct CadetChannel`. | ||
799 | * @param cid identifier of the connection within the tunnel, NULL | ||
800 | * if transmission failed | ||
801 | */ | ||
802 | static void | ||
803 | send_ack_cb (void *cls, | ||
804 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
805 | { | ||
806 | struct CadetChannel *ch = cls; | ||
807 | |||
808 | GNUNET_assert (NULL != ch->last_control_qe); | ||
809 | ch->last_control_qe = NULL; | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer. | ||
815 | * | ||
816 | * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for | ||
817 | */ | ||
818 | static void | ||
819 | send_channel_data_ack (struct CadetChannel *ch) | ||
820 | { | ||
821 | struct GNUNET_CADET_ChannelDataAckMessage msg; | ||
822 | |||
823 | if (GNUNET_NO == ch->reliable) | ||
824 | return; /* no ACKs */ | ||
825 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | ||
826 | msg.header.size = htons (sizeof(msg)); | ||
827 | msg.ctn = ch->ctn; | ||
828 | msg.mid.mid = htonl (ntohl (ch->mid_recv.mid)); | ||
829 | msg.futures = GNUNET_htonll (ch->mid_futures); | ||
830 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
831 | "Sending DATA_ACK %u:%llX via %s\n", | ||
832 | (unsigned int) ntohl (msg.mid.mid), | ||
833 | (unsigned long long) ch->mid_futures, | ||
834 | GCCH_2s (ch)); | ||
835 | if (NULL != ch->last_control_qe) | ||
836 | GCT_send_cancel (ch->last_control_qe); | ||
837 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
838 | &msg.ctn); | ||
839 | } | ||
840 | |||
841 | |||
842 | /** | ||
843 | * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the | ||
844 | * connection is up. | ||
845 | * | ||
846 | * @param cls the `struct CadetChannel` | ||
847 | */ | ||
848 | static void | ||
849 | send_open_ack (void *cls) | ||
850 | { | ||
851 | struct CadetChannel *ch = cls; | ||
852 | struct GNUNET_CADET_ChannelOpenAckMessage msg; | ||
853 | |||
854 | ch->retry_control_task = NULL; | ||
855 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
856 | "Sending CHANNEL_OPEN_ACK on %s\n", | ||
857 | GCCH_2s (ch)); | ||
858 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | ||
859 | msg.header.size = htons (sizeof(msg)); | ||
860 | msg.reserved = htonl (0); | ||
861 | msg.ctn = ch->ctn; | ||
862 | msg.port = ch->port; | ||
863 | if (NULL != ch->last_control_qe) | ||
864 | GCT_send_cancel (ch->last_control_qe); | ||
865 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
866 | &msg.ctn); | ||
867 | } | ||
868 | |||
869 | |||
870 | /** | ||
871 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
872 | * this channel. If the binding was successful, (re)transmit the | ||
873 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
874 | * | ||
875 | * @param ch channel that got the duplicate open | ||
876 | * @param cti identifier of the connection that delivered the message | ||
877 | */ | ||
878 | void | ||
879 | GCCH_handle_duplicate_open ( | ||
880 | struct CadetChannel *ch, | ||
881 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
882 | { | ||
883 | if (NULL == ch->dest) | ||
884 | { | ||
885 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
886 | "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n", | ||
887 | GCCH_2s (ch)); | ||
888 | return; | ||
889 | } | ||
890 | if (NULL != ch->retry_control_task) | ||
891 | { | ||
892 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
893 | "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n", | ||
894 | GCCH_2s (ch)); | ||
895 | return; | ||
896 | } | ||
897 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
898 | "Retransmitting CHANNEL_OPEN_ACK on %s\n", | ||
899 | GCCH_2s (ch)); | ||
900 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages. | ||
906 | * | ||
907 | * @param ch channel the ack is for | ||
908 | * @param to_owner #GNUNET_YES to send to owner, | ||
909 | * #GNUNET_NO to send to dest | ||
910 | */ | ||
911 | static void | ||
912 | send_ack_to_client (struct CadetChannel *ch, int to_owner) | ||
913 | { | ||
914 | struct GNUNET_MQ_Envelope *env; | ||
915 | struct GNUNET_CADET_LocalAck *ack; | ||
916 | struct CadetChannelClient *ccc; | ||
917 | |||
918 | ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest; | ||
919 | if (NULL == ccc) | ||
920 | { | ||
921 | /* This can happen if we are just getting ACKs after | ||
922 | our local client already disconnected. */ | ||
923 | GNUNET_assert (GNUNET_YES == ch->destroy); | ||
924 | return; | ||
925 | } | ||
926 | env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
927 | ack->ccn = ccc->ccn; | ||
928 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
929 | "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n", | ||
930 | GSC_2s (ccc->c), | ||
931 | (GNUNET_YES == to_owner) ? "owner" : "dest", | ||
932 | ntohl (ack->ccn.channel_of_client), | ||
933 | ch->pending_messages, | ||
934 | ch->max_pending_messages); | ||
935 | GSC_send_to_client (ccc->c, env); | ||
936 | } | ||
937 | |||
938 | |||
939 | void | ||
940 | GCCH_bind (struct CadetChannel *ch, | ||
941 | struct CadetClient *c, | ||
942 | const struct GNUNET_HashCode *port) | ||
943 | { | ||
944 | uint32_t options; | ||
945 | struct CadetChannelClient *cccd; | ||
946 | |||
947 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
948 | "Binding %s from %s to port %s of %s\n", | ||
949 | GCCH_2s (ch), | ||
950 | GCT_2s (ch->t), | ||
951 | GNUNET_h2s (&ch->port), | ||
952 | GSC_2s (c)); | ||
953 | if (NULL != ch->retry_control_task) | ||
954 | { | ||
955 | /* there might be a timeout task here */ | ||
956 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
957 | ch->retry_control_task = NULL; | ||
958 | } | ||
959 | options = 0; | ||
960 | cccd = GNUNET_new (struct CadetChannelClient); | ||
961 | GNUNET_assert (NULL == ch->dest); | ||
962 | ch->dest = cccd; | ||
963 | ch->port = *port; | ||
964 | cccd->c = c; | ||
965 | cccd->client_ready = GNUNET_YES; | ||
966 | cccd->ccn = GSC_bind (c, | ||
967 | ch, | ||
968 | (GNUNET_YES == ch->is_loopback) | ||
969 | ? GCP_get (&my_full_id, GNUNET_YES) | ||
970 | : GCT_get_destination (ch->t), | ||
971 | port, | ||
972 | options); | ||
973 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
974 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
975 | ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */ | ||
976 | if (GNUNET_YES == ch->is_loopback) | ||
977 | { | ||
978 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
979 | GCCH_handle_channel_open_ack (ch, NULL, port); | ||
980 | } | ||
981 | else | ||
982 | { | ||
983 | /* notify other peer that we accepted the connection */ | ||
984 | ch->state = CADET_CHANNEL_READY; | ||
985 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
986 | } | ||
987 | /* give client it's initial supply of ACKs */ | ||
988 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
989 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
990 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
991 | send_ack_to_client (ch, GNUNET_NO); | ||
992 | } | ||
993 | |||
994 | |||
995 | /** | ||
996 | * One of our clients has disconnected, tell the other one that we | ||
997 | * are finished. Done asynchronously to avoid concurrent modification | ||
998 | * issues if this is the same client. | ||
999 | * | ||
1000 | * @param cls the `struct CadetChannel` where one of the ends is now dead | ||
1001 | */ | ||
1002 | static void | ||
1003 | signal_remote_destroy_cb (void *cls) | ||
1004 | { | ||
1005 | struct CadetChannel *ch = cls; | ||
1006 | struct CadetChannelClient *ccc; | ||
1007 | |||
1008 | /* Find which end is left... */ | ||
1009 | ch->retry_control_task = NULL; | ||
1010 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1011 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1012 | channel_destroy (ch); | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /** | ||
1017 | * Destroy locally created channel. Called by the local client, so no | ||
1018 | * need to tell the client. | ||
1019 | * | ||
1020 | * @param ch channel to destroy | ||
1021 | * @param c client that caused the destruction | ||
1022 | * @param ccn client number of the client @a c | ||
1023 | */ | ||
1024 | void | ||
1025 | GCCH_channel_local_destroy (struct CadetChannel *ch, | ||
1026 | struct CadetClient *c, | ||
1027 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1028 | { | ||
1029 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1030 | "%s asks for destruction of %s\n", | ||
1031 | GSC_2s (c), | ||
1032 | GCCH_2s (ch)); | ||
1033 | GNUNET_assert (NULL != c); | ||
1034 | if ((NULL != ch->owner) && (c == ch->owner->c) && | ||
1035 | (ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1036 | { | ||
1037 | free_channel_client (ch->owner); | ||
1038 | ch->owner = NULL; | ||
1039 | } | ||
1040 | else if ((NULL != ch->dest) && (c == ch->dest->c) && | ||
1041 | (ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1042 | { | ||
1043 | free_channel_client (ch->dest); | ||
1044 | ch->dest = NULL; | ||
1045 | } | ||
1046 | else | ||
1047 | { | ||
1048 | GNUNET_assert (0); | ||
1049 | } | ||
1050 | |||
1051 | if (GNUNET_YES == ch->destroy) | ||
1052 | { | ||
1053 | /* other end already destroyed, with the local client gone, no need | ||
1054 | to finish transmissions, just destroy immediately. */ | ||
1055 | channel_destroy (ch); | ||
1056 | return; | ||
1057 | } | ||
1058 | if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1059 | { | ||
1060 | /* Wait for other end to destroy us as well, | ||
1061 | and otherwise allow send queue to be transmitted first */ | ||
1062 | ch->destroy = GNUNET_YES; | ||
1063 | return; | ||
1064 | } | ||
1065 | if ((GNUNET_YES == ch->is_loopback) && | ||
1066 | ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1067 | { | ||
1068 | if (NULL != ch->retry_control_task) | ||
1069 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1070 | ch->retry_control_task = | ||
1071 | GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch); | ||
1072 | return; | ||
1073 | } | ||
1074 | if (GNUNET_NO == ch->is_loopback) | ||
1075 | { | ||
1076 | /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */ | ||
1077 | switch (ch->state) | ||
1078 | { | ||
1079 | case CADET_CHANNEL_NEW: | ||
1080 | /* We gave up on a channel that we created as a client to a remote | ||
1081 | target, but that never went anywhere. Nothing to do here. */ | ||
1082 | break; | ||
1083 | |||
1084 | case CADET_CHANNEL_LOOSE: | ||
1085 | break; | ||
1086 | |||
1087 | default: | ||
1088 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1089 | } | ||
1090 | } | ||
1091 | /* Nothing left to do, just finish destruction */ | ||
1092 | channel_destroy (ch); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | void | ||
1097 | GCCH_handle_channel_open_ack ( | ||
1098 | struct CadetChannel *ch, | ||
1099 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1100 | const struct GNUNET_HashCode *port) | ||
1101 | { | ||
1102 | switch (ch->state) | ||
1103 | { | ||
1104 | case CADET_CHANNEL_NEW: | ||
1105 | /* this should be impossible */ | ||
1106 | GNUNET_break (0); | ||
1107 | break; | ||
1108 | |||
1109 | case CADET_CHANNEL_LOOSE: | ||
1110 | /* This makes no sense. */ | ||
1111 | GNUNET_break_op (0); | ||
1112 | break; | ||
1113 | |||
1114 | case CADET_CHANNEL_OPEN_SENT: | ||
1115 | if (NULL == ch->owner) | ||
1116 | { | ||
1117 | /* We're not the owner, wrong direction! */ | ||
1118 | GNUNET_break_op (0); | ||
1119 | return; | ||
1120 | } | ||
1121 | if (0 != GNUNET_memcmp (&ch->port, port)) | ||
1122 | { | ||
1123 | /* Other peer failed to provide the right port, | ||
1124 | refuse connection. */ | ||
1125 | GNUNET_break_op (0); | ||
1126 | return; | ||
1127 | } | ||
1128 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1129 | "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n", | ||
1130 | GCCH_2s (ch)); | ||
1131 | if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */ | ||
1132 | { | ||
1133 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1134 | ch->retry_control_task = NULL; | ||
1135 | } | ||
1136 | ch->state = CADET_CHANNEL_READY; | ||
1137 | /* On first connect, send client as many ACKs as we allow messages | ||
1138 | to be buffered! */ | ||
1139 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
1140 | send_ack_to_client (ch, GNUNET_YES); | ||
1141 | break; | ||
1142 | |||
1143 | case CADET_CHANNEL_READY: | ||
1144 | /* duplicate ACK, maybe we retried the CREATE. Ignore. */ | ||
1145 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1146 | "Received duplicate channel OPEN_ACK for %s\n", | ||
1147 | GCCH_2s (ch)); | ||
1148 | GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO); | ||
1149 | break; | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | /** | ||
1155 | * Test if element @a e1 comes before element @a e2. | ||
1156 | * | ||
1157 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1158 | * @param m1 a message of to sort | ||
1159 | * @param m2 another message to sort | ||
1160 | * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO | ||
1161 | */ | ||
1162 | static int | ||
1163 | is_before (void *cls, | ||
1164 | struct CadetOutOfOrderMessage *m1, | ||
1165 | struct CadetOutOfOrderMessage *m2) | ||
1166 | { | ||
1167 | int *duplicate = cls; | ||
1168 | uint32_t v1 = ntohl (m1->mid.mid); | ||
1169 | uint32_t v2 = ntohl (m2->mid.mid); | ||
1170 | uint32_t delta; | ||
1171 | |||
1172 | delta = v2 - v1; | ||
1173 | if (0 == delta) | ||
1174 | *duplicate = GNUNET_YES; | ||
1175 | if (delta > (uint32_t) INT_MAX) | ||
1176 | { | ||
1177 | /* in overflow range, we can safely assume we wrapped around */ | ||
1178 | return GNUNET_NO; | ||
1179 | } | ||
1180 | else | ||
1181 | { | ||
1182 | /* result is small, thus v2 > v1, thus m1 < m2 */ | ||
1183 | return GNUNET_YES; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1187 | |||
1188 | void | ||
1189 | GCCH_handle_channel_plaintext_data ( | ||
1190 | struct CadetChannel *ch, | ||
1191 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1192 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
1193 | { | ||
1194 | struct GNUNET_MQ_Envelope *env; | ||
1195 | struct GNUNET_CADET_LocalData *ld; | ||
1196 | struct CadetChannelClient *ccc; | ||
1197 | size_t payload_size; | ||
1198 | struct CadetOutOfOrderMessage *com; | ||
1199 | int duplicate; | ||
1200 | uint32_t mid_min; | ||
1201 | uint32_t mid_max; | ||
1202 | uint32_t mid_msg; | ||
1203 | uint32_t delta; | ||
1204 | |||
1205 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1206 | if ((NULL == ch->owner) && (NULL == ch->dest)) | ||
1207 | { | ||
1208 | /* This client is gone, but we still have messages to send to | ||
1209 | the other end (which is why @a ch is not yet dead). However, | ||
1210 | we cannot pass messages to our client anymore. */ | ||
1211 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1212 | "Dropping incoming payload on %s as this end is already closed\n", | ||
1213 | GCCH_2s (ch)); | ||
1214 | /* send back DESTROY notification to stop further retransmissions! */ | ||
1215 | if (GNUNET_YES == ch->destroy) | ||
1216 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1217 | return; | ||
1218 | } | ||
1219 | payload_size = ntohs (msg->header.size) - sizeof(*msg); | ||
1220 | env = GNUNET_MQ_msg_extra (ld, | ||
1221 | payload_size, | ||
1222 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1223 | ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn; | ||
1224 | GNUNET_memcpy (&ld[1], &msg[1], payload_size); | ||
1225 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1226 | if (GNUNET_YES == ccc->client_ready) | ||
1227 | { | ||
1228 | /* | ||
1229 | * We ad-hoc send the message if | ||
1230 | * - The channel is out-of-order | ||
1231 | * - The channel is reliable and MID matches next expected MID | ||
1232 | * - The channel is unreliable and MID is before lowest seen MID | ||
1233 | */if ((GNUNET_YES == ch->out_of_order) || | ||
1234 | ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) || | ||
1235 | ((GNUNET_NO == ch->reliable) && | ||
1236 | (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) && | ||
1237 | ((NULL == ccc->head_recv) || | ||
1238 | (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid))))) | ||
1239 | { | ||
1240 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1241 | "Giving %u bytes of payload with MID %u from %s to client %s\n", | ||
1242 | (unsigned int) payload_size, | ||
1243 | ntohl (msg->mid.mid), | ||
1244 | GCCH_2s (ch), | ||
1245 | GSC_2s (ccc->c)); | ||
1246 | ccc->client_ready = GNUNET_NO; | ||
1247 | GSC_send_to_client (ccc->c, env); | ||
1248 | if (GNUNET_NO == ch->out_of_order) | ||
1249 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1250 | else | ||
1251 | ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); | ||
1252 | ch->mid_futures >>= 1; | ||
1253 | if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable)) | ||
1254 | { | ||
1255 | /* possibly shift by more if we skipped messages */ | ||
1256 | uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid); | ||
1257 | |||
1258 | if (delta > 63) | ||
1259 | ch->mid_futures = 0; | ||
1260 | else | ||
1261 | ch->mid_futures >>= delta; | ||
1262 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1263 | } | ||
1264 | send_channel_data_ack (ch); | ||
1265 | return; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | if (GNUNET_YES == ch->reliable) | ||
1270 | { | ||
1271 | /* check if message ought to be dropped because it is ancient/too distant/duplicate */ | ||
1272 | mid_min = ntohl (ch->mid_recv.mid); | ||
1273 | mid_max = mid_min + ch->max_pending_messages; | ||
1274 | mid_msg = ntohl (msg->mid.mid); | ||
1275 | if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) || | ||
1276 | ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages)) | ||
1277 | { | ||
1278 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1279 | "%s at %u drops ancient or far-future message %u\n", | ||
1280 | GCCH_2s (ch), | ||
1281 | (unsigned int) mid_min, | ||
1282 | ntohl (msg->mid.mid)); | ||
1283 | |||
1284 | GNUNET_STATISTICS_update (stats, | ||
1285 | "# duplicate DATA (ancient or future)", | ||
1286 | 1, | ||
1287 | GNUNET_NO); | ||
1288 | GNUNET_MQ_discard (env); | ||
1289 | send_channel_data_ack (ch); | ||
1290 | return; | ||
1291 | } | ||
1292 | /* mark bit for future ACKs */ | ||
1293 | delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */ | ||
1294 | if (delta < 64) | ||
1295 | { | ||
1296 | if (0 != (ch->mid_futures & (1LLU << delta))) | ||
1297 | { | ||
1298 | /* Duplicate within the queue, drop also */ | ||
1299 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1300 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1301 | (unsigned int) payload_size, | ||
1302 | GCCH_2s (ch), | ||
1303 | ntohl (msg->mid.mid)); | ||
1304 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1305 | GNUNET_MQ_discard (env); | ||
1306 | send_channel_data_ack (ch); | ||
1307 | return; | ||
1308 | } | ||
1309 | ch->mid_futures |= (1LLU << delta); | ||
1310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1311 | "Marked bit %llX for mid %u (base: %u); now: %llX\n", | ||
1312 | (1LLU << delta), | ||
1313 | mid_msg, | ||
1314 | mid_min, | ||
1315 | (unsigned long long) ch->mid_futures); | ||
1316 | } | ||
1317 | } | ||
1318 | else /* ! ch->reliable */ | ||
1319 | { | ||
1320 | struct CadetOutOfOrderMessage *next_msg; | ||
1321 | |||
1322 | /** | ||
1323 | * We always send if possible in this case. | ||
1324 | * It is guaranteed that the queued MID < received MID | ||
1325 | **/ | ||
1326 | if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready)) | ||
1327 | { | ||
1328 | next_msg = ccc->head_recv; | ||
1329 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1330 | "Giving queued MID %u from %s to client %s\n", | ||
1331 | ntohl (next_msg->mid.mid), | ||
1332 | GCCH_2s (ch), | ||
1333 | GSC_2s (ccc->c)); | ||
1334 | ccc->client_ready = GNUNET_NO; | ||
1335 | GSC_send_to_client (ccc->c, next_msg->env); | ||
1336 | ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid)); | ||
1337 | ch->mid_futures >>= 1; | ||
1338 | send_channel_data_ack (ch); | ||
1339 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg); | ||
1340 | ccc->num_recv--; | ||
1341 | /* Do not process duplicate MID */ | ||
1342 | if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */ | ||
1343 | { | ||
1344 | /* Duplicate within the queue, drop */ | ||
1345 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1346 | "Message on %s (mid %u) dropped, duplicate\n", | ||
1347 | GCCH_2s (ch), | ||
1348 | ntohl (msg->mid.mid)); | ||
1349 | GNUNET_free (next_msg); | ||
1350 | GNUNET_MQ_discard (env); | ||
1351 | return; | ||
1352 | } | ||
1353 | GNUNET_free (next_msg); | ||
1354 | } | ||
1355 | |||
1356 | if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */ | ||
1357 | { | ||
1358 | /* Duplicate within the queue, drop */ | ||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1360 | "Message on %s (mid %u) dropped, old.\n", | ||
1361 | GCCH_2s (ch), | ||
1362 | ntohl (msg->mid.mid)); | ||
1363 | GNUNET_MQ_discard (env); | ||
1364 | return; | ||
1365 | } | ||
1366 | |||
1367 | /* Channel is unreliable, so we do not ACK. But we also cannot | ||
1368 | allow buffering everything, so check if we have space... */ | ||
1369 | if (ccc->num_recv >= ch->max_pending_messages) | ||
1370 | { | ||
1371 | struct CadetOutOfOrderMessage *drop; | ||
1372 | |||
1373 | /* Yep, need to drop. Drop the oldest message in | ||
1374 | the buffer. */ | ||
1375 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1376 | "Queue full due slow client on %s, dropping oldest message\n", | ||
1377 | GCCH_2s (ch)); | ||
1378 | GNUNET_STATISTICS_update (stats, | ||
1379 | "# messages dropped due to slow client", | ||
1380 | 1, | ||
1381 | GNUNET_NO); | ||
1382 | drop = ccc->head_recv; | ||
1383 | GNUNET_assert (NULL != drop); | ||
1384 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop); | ||
1385 | ccc->num_recv--; | ||
1386 | GNUNET_MQ_discard (drop->env); | ||
1387 | GNUNET_free (drop); | ||
1388 | } | ||
1389 | } | ||
1390 | |||
1391 | /* Insert message into sorted out-of-order queue */ | ||
1392 | com = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1393 | com->mid = msg->mid; | ||
1394 | com->env = env; | ||
1395 | duplicate = GNUNET_NO; | ||
1396 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage, | ||
1397 | is_before, | ||
1398 | &duplicate, | ||
1399 | ccc->head_recv, | ||
1400 | ccc->tail_recv, | ||
1401 | com); | ||
1402 | ccc->num_recv++; | ||
1403 | if (GNUNET_YES == duplicate) | ||
1404 | { | ||
1405 | /* Duplicate within the queue, drop also (this is not covered by | ||
1406 | the case above if "delta" >= 64, which could be the case if | ||
1407 | max_pending_messages is also >= 64 or if our client is unready | ||
1408 | and we are seeing retransmissions of the message our client is | ||
1409 | blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1410 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1411 | (unsigned int) payload_size, | ||
1412 | GCCH_2s (ch), | ||
1413 | ntohl (msg->mid.mid)); | ||
1414 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1415 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1416 | ccc->num_recv--; | ||
1417 | GNUNET_MQ_discard (com->env); | ||
1418 | GNUNET_free (com); | ||
1419 | send_channel_data_ack (ch); | ||
1420 | return; | ||
1421 | } | ||
1422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1423 | "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n", | ||
1424 | (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready", | ||
1425 | (unsigned int) payload_size, | ||
1426 | GCCH_2s (ch), | ||
1427 | ntohl (ccc->ccn.channel_of_client), | ||
1428 | ccc, | ||
1429 | ntohl (msg->mid.mid), | ||
1430 | ntohl (ch->mid_recv.mid)); | ||
1431 | /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and | ||
1432 | the sender may already be transmitting the previous one. Needs | ||
1433 | experimental evaluation to see if/when this ACK helps or | ||
1434 | hurts. (We might even want another option.) */ | ||
1435 | send_channel_data_ack (ch); | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * Function called once the tunnel has sent one of our messages. | ||
1441 | * If the message is unreliable, simply frees the `crm`. If the | ||
1442 | * message was reliable, calculate retransmission time and | ||
1443 | * wait for ACK (or retransmit). | ||
1444 | * | ||
1445 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1446 | * @param cid identifier of the connection within the tunnel, NULL | ||
1447 | * if transmission failed | ||
1448 | */ | ||
1449 | static void | ||
1450 | data_sent_cb (void *cls, | ||
1451 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * We need to retry a transmission, the last one took too long to | ||
1456 | * be acknowledged. | ||
1457 | * | ||
1458 | * @param cls the `struct CadetChannel` where we need to retransmit | ||
1459 | */ | ||
1460 | static void | ||
1461 | retry_transmission (void *cls) | ||
1462 | { | ||
1463 | struct CadetChannel *ch = cls; | ||
1464 | struct CadetReliableMessage *crm = ch->head_sent; | ||
1465 | |||
1466 | ch->retry_data_task = NULL; | ||
1467 | GNUNET_assert (NULL == crm->qe); | ||
1468 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1469 | "Retrying transmission on %s of message %u\n", | ||
1470 | GCCH_2s (ch), | ||
1471 | (unsigned int) ntohl (crm->data_message->mid.mid)); | ||
1472 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1473 | &crm->data_message->ctn); | ||
1474 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from | ||
1480 | * the queue and tell our client that it can send more. | ||
1481 | * | ||
1482 | * @param ch the channel that got the PLAINTEXT_DATA_ACK | ||
1483 | * @param cti identifier of the connection that delivered the message | ||
1484 | * @param crm the message that got acknowledged | ||
1485 | */ | ||
1486 | static void | ||
1487 | handle_matching_ack (struct CadetChannel *ch, | ||
1488 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1489 | struct CadetReliableMessage *crm) | ||
1490 | { | ||
1491 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1492 | ch->pending_messages--; | ||
1493 | GNUNET_assert (ch->pending_messages < ch->max_pending_messages); | ||
1494 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1495 | "Received DATA_ACK on %s for message %u (%u ACKs pending)\n", | ||
1496 | GCCH_2s (ch), | ||
1497 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1498 | ch->pending_messages); | ||
1499 | if (NULL != crm->qe) | ||
1500 | { | ||
1501 | GCT_send_cancel (crm->qe); | ||
1502 | crm->qe = NULL; | ||
1503 | } | ||
1504 | if ((1 == crm->num_transmissions) && (NULL != cti)) | ||
1505 | { | ||
1506 | GCC_ack_observed (cti); | ||
1507 | if (0 == GNUNET_memcmp (cti, &crm->connection_taken)) | ||
1508 | { | ||
1509 | GCC_latency_observed (cti, | ||
1510 | GNUNET_TIME_absolute_get_duration ( | ||
1511 | crm->first_transmission_time)); | ||
1512 | } | ||
1513 | } | ||
1514 | GNUNET_free (crm->data_message); | ||
1515 | GNUNET_free (crm); | ||
1516 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1517 | } | ||
1518 | |||
1519 | |||
1520 | /** | ||
1521 | * We got an acknowledgement for payload data for a channel. | ||
1522 | * Possibly resume transmissions. | ||
1523 | * | ||
1524 | * @param ch channel that got the ack | ||
1525 | * @param cti identifier of the connection that delivered the message | ||
1526 | * @param ack details about what was received | ||
1527 | */ | ||
1528 | void | ||
1529 | GCCH_handle_channel_plaintext_data_ack ( | ||
1530 | struct CadetChannel *ch, | ||
1531 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1532 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
1533 | { | ||
1534 | struct CadetReliableMessage *crm; | ||
1535 | struct CadetReliableMessage *crmn; | ||
1536 | int found; | ||
1537 | uint32_t mid_base; | ||
1538 | uint64_t mid_mask; | ||
1539 | unsigned int delta; | ||
1540 | |||
1541 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1542 | if (GNUNET_NO == ch->reliable) | ||
1543 | { | ||
1544 | /* not expecting ACKs on unreliable channel, odd */ | ||
1545 | GNUNET_break_op (0); | ||
1546 | return; | ||
1547 | } | ||
1548 | /* mid_base is the MID of the next message that the | ||
1549 | other peer expects (i.e. that is missing!), everything | ||
1550 | LOWER (but excluding mid_base itself) was received. */ | ||
1551 | mid_base = ntohl (ack->mid.mid); | ||
1552 | mid_mask = GNUNET_htonll (ack->futures); | ||
1553 | found = GNUNET_NO; | ||
1554 | for (crm = ch->head_sent; NULL != crm; crm = crmn) | ||
1555 | { | ||
1556 | crmn = crm->next; | ||
1557 | delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base); | ||
1558 | if (delta >= UINT_MAX - ch->max_pending_messages) | ||
1559 | { | ||
1560 | /* overflow, means crm was a bit in the past, so this ACK counts for it. */ | ||
1561 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1562 | "Got DATA_ACK with base %u satisfying past message %u on %s\n", | ||
1563 | (unsigned int) mid_base, | ||
1564 | ntohl (crm->data_message->mid.mid), | ||
1565 | GCCH_2s (ch)); | ||
1566 | handle_matching_ack (ch, cti, crm); | ||
1567 | found = GNUNET_YES; | ||
1568 | continue; | ||
1569 | } | ||
1570 | delta--; | ||
1571 | if (delta >= 64) | ||
1572 | continue; | ||
1573 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1574 | "Testing bit %llX for mid %u (base: %u)\n", | ||
1575 | (1LLU << delta), | ||
1576 | ntohl (crm->data_message->mid.mid), | ||
1577 | mid_base); | ||
1578 | if (0 != (mid_mask & (1LLU << delta))) | ||
1579 | { | ||
1580 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1581 | "Got DATA_ACK with mask for %u on %s\n", | ||
1582 | ntohl (crm->data_message->mid.mid), | ||
1583 | GCCH_2s (ch)); | ||
1584 | handle_matching_ack (ch, cti, crm); | ||
1585 | found = GNUNET_YES; | ||
1586 | } | ||
1587 | } | ||
1588 | if (GNUNET_NO == found) | ||
1589 | { | ||
1590 | /* ACK for message we already dropped, might have been a | ||
1591 | duplicate ACK? Ignore. */ | ||
1592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1593 | "Duplicate DATA_ACK on %s, ignoring\n", | ||
1594 | GCCH_2s (ch)); | ||
1595 | GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO); | ||
1596 | return; | ||
1597 | } | ||
1598 | if (NULL != ch->retry_data_task) | ||
1599 | { | ||
1600 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1601 | ch->retry_data_task = NULL; | ||
1602 | } | ||
1603 | if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe)) | ||
1604 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1605 | &retry_transmission, | ||
1606 | ch); | ||
1607 | } | ||
1608 | |||
1609 | |||
1610 | void | ||
1611 | GCCH_handle_remote_destroy ( | ||
1612 | struct CadetChannel *ch, | ||
1613 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
1614 | { | ||
1615 | struct CadetChannelClient *ccc; | ||
1616 | |||
1617 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1618 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1619 | "Received remote channel DESTROY for %s\n", | ||
1620 | GCCH_2s (ch)); | ||
1621 | if (GNUNET_YES == ch->destroy) | ||
1622 | { | ||
1623 | /* Local client already gone, this is instant-death. */ | ||
1624 | channel_destroy (ch); | ||
1625 | return; | ||
1626 | } | ||
1627 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1628 | if ((NULL != ccc) && (NULL != ccc->head_recv)) | ||
1629 | { | ||
1630 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1631 | "Lost end of transmission due to remote shutdown on %s\n", | ||
1632 | GCCH_2s (ch)); | ||
1633 | /* FIXME: change API to notify client about truncated transmission! */ | ||
1634 | } | ||
1635 | ch->destroy = GNUNET_YES; | ||
1636 | if (NULL != ccc) | ||
1637 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1638 | channel_destroy (ch); | ||
1639 | } | ||
1640 | |||
1641 | |||
1642 | /** | ||
1643 | * Test if element @a e1 comes before element @a e2. | ||
1644 | * | ||
1645 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1646 | * @param crm1 an element of to sort | ||
1647 | * @param crm2 another element to sort | ||
1648 | * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO | ||
1649 | */ | ||
1650 | static int | ||
1651 | cmp_crm_by_next_retry (void *cls, | ||
1652 | struct CadetReliableMessage *crm1, | ||
1653 | struct CadetReliableMessage *crm2) | ||
1654 | { | ||
1655 | if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us) | ||
1656 | return GNUNET_YES; | ||
1657 | return GNUNET_NO; | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /** | ||
1662 | * Function called once the tunnel has sent one of our messages. | ||
1663 | * If the message is unreliable, simply frees the `crm`. If the | ||
1664 | * message was reliable, calculate retransmission time and | ||
1665 | * wait for ACK (or retransmit). | ||
1666 | * | ||
1667 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1668 | * @param cid identifier of the connection within the tunnel, NULL | ||
1669 | * if transmission failed | ||
1670 | */ | ||
1671 | static void | ||
1672 | data_sent_cb (void *cls, | ||
1673 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
1674 | { | ||
1675 | struct CadetReliableMessage *crm = cls; | ||
1676 | struct CadetChannel *ch = crm->ch; | ||
1677 | |||
1678 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1679 | GNUNET_assert (NULL != crm->qe); | ||
1680 | crm->qe = NULL; | ||
1681 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1682 | if (GNUNET_NO == ch->reliable) | ||
1683 | { | ||
1684 | GNUNET_free (crm->data_message); | ||
1685 | GNUNET_free (crm); | ||
1686 | ch->pending_messages--; | ||
1687 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1688 | return; | ||
1689 | } | ||
1690 | if (NULL == cid) | ||
1691 | { | ||
1692 | /* There was an error sending. */ | ||
1693 | crm->num_transmissions = GNUNET_SYSERR; | ||
1694 | } | ||
1695 | else if (GNUNET_SYSERR != crm->num_transmissions) | ||
1696 | { | ||
1697 | /* Increment transmission counter, and possibly store @a cid | ||
1698 | if this was the first transmission. */ | ||
1699 | crm->num_transmissions++; | ||
1700 | if (1 == crm->num_transmissions) | ||
1701 | { | ||
1702 | crm->first_transmission_time = GNUNET_TIME_absolute_get (); | ||
1703 | crm->connection_taken = *cid; | ||
1704 | GCC_ack_expected (cid); | ||
1705 | } | ||
1706 | } | ||
1707 | if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid)) | ||
1708 | { | ||
1709 | struct CadetConnection *cc = GCC_lookup (cid); | ||
1710 | |||
1711 | if (NULL != cc) | ||
1712 | crm->retry_delay = GCC_get_metrics (cc)->aged_latency; | ||
1713 | else | ||
1714 | crm->retry_delay = ch->retry_time; | ||
1715 | } | ||
1716 | crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay); | ||
1717 | crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY); | ||
1718 | crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay); | ||
1719 | |||
1720 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage, | ||
1721 | cmp_crm_by_next_retry, | ||
1722 | NULL, | ||
1723 | ch->head_sent, | ||
1724 | ch->tail_sent, | ||
1725 | crm); | ||
1726 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1727 | "Message %u sent, next transmission on %s in %s\n", | ||
1728 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1729 | GCCH_2s (ch), | ||
1730 | GNUNET_STRINGS_relative_time_to_string ( | ||
1731 | GNUNET_TIME_absolute_get_remaining ( | ||
1732 | ch->head_sent->next_retry), | ||
1733 | GNUNET_YES)); | ||
1734 | if (NULL == ch->head_sent->qe) | ||
1735 | { | ||
1736 | if (NULL != ch->retry_data_task) | ||
1737 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1738 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1739 | &retry_transmission, | ||
1740 | ch); | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | |||
1745 | /** | ||
1746 | * Handle data given by a client. | ||
1747 | * | ||
1748 | * Check whether the client is allowed to send in this tunnel, save if | ||
1749 | * channel is reliable and send an ACK to the client if there is still | ||
1750 | * buffer space in the tunnel. | ||
1751 | * | ||
1752 | * @param ch Channel. | ||
1753 | * @param sender_ccn ccn of the sender | ||
1754 | * @param buf payload to transmit. | ||
1755 | * @param buf_len number of bytes in @a buf | ||
1756 | * @return #GNUNET_OK if everything goes well, | ||
1757 | * #GNUNET_SYSERR in case of an error. | ||
1758 | */ | ||
1759 | int | ||
1760 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
1761 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
1762 | const char *buf, | ||
1763 | size_t buf_len) | ||
1764 | { | ||
1765 | struct CadetReliableMessage *crm; | ||
1766 | |||
1767 | if (ch->pending_messages >= ch->max_pending_messages) | ||
1768 | { | ||
1769 | GNUNET_break (0); /* Fails: #5370 */ | ||
1770 | return GNUNET_SYSERR; | ||
1771 | } | ||
1772 | if (GNUNET_YES == ch->destroy) | ||
1773 | { | ||
1774 | /* we are going down, drop messages */ | ||
1775 | return GNUNET_OK; | ||
1776 | } | ||
1777 | ch->pending_messages++; | ||
1778 | |||
1779 | if (GNUNET_YES == ch->is_loopback) | ||
1780 | { | ||
1781 | struct CadetChannelClient *receiver; | ||
1782 | struct GNUNET_MQ_Envelope *env; | ||
1783 | struct GNUNET_CADET_LocalData *ld; | ||
1784 | int ack_to_owner; | ||
1785 | |||
1786 | env = | ||
1787 | GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1788 | if ((NULL != ch->owner) && | ||
1789 | (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1790 | { | ||
1791 | receiver = ch->dest; | ||
1792 | ack_to_owner = GNUNET_YES; | ||
1793 | } | ||
1794 | else if ((NULL != ch->dest) && | ||
1795 | (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1796 | { | ||
1797 | receiver = ch->owner; | ||
1798 | ack_to_owner = GNUNET_NO; | ||
1799 | } | ||
1800 | else | ||
1801 | { | ||
1802 | GNUNET_free (env); | ||
1803 | GNUNET_break (0); | ||
1804 | return GNUNET_SYSERR; | ||
1805 | } | ||
1806 | GNUNET_assert (NULL != receiver); | ||
1807 | ld->ccn = receiver->ccn; | ||
1808 | GNUNET_memcpy (&ld[1], buf, buf_len); | ||
1809 | if (GNUNET_YES == receiver->client_ready) | ||
1810 | { | ||
1811 | ch->pending_messages--; | ||
1812 | GSC_send_to_client (receiver->c, env); | ||
1813 | send_ack_to_client (ch, ack_to_owner); | ||
1814 | } | ||
1815 | else | ||
1816 | { | ||
1817 | struct CadetOutOfOrderMessage *oom; | ||
1818 | |||
1819 | oom = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1820 | oom->env = env; | ||
1821 | GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv, | ||
1822 | receiver->tail_recv, | ||
1823 | oom); | ||
1824 | receiver->num_recv++; | ||
1825 | } | ||
1826 | return GNUNET_OK; | ||
1827 | } | ||
1828 | |||
1829 | /* Everything is correct, send the message. */ | ||
1830 | crm = GNUNET_malloc (sizeof(*crm)); | ||
1831 | crm->ch = ch; | ||
1832 | crm->data_message = GNUNET_malloc ( | ||
1833 | sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1834 | crm->data_message->header.size = | ||
1835 | htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1836 | crm->data_message->header.type = | ||
1837 | htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1838 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1839 | crm->data_message->mid = ch->mid_send; | ||
1840 | crm->data_message->ctn = ch->ctn; | ||
1841 | GNUNET_memcpy (&crm->data_message[1], buf, buf_len); | ||
1842 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm); | ||
1843 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1844 | "Sending message %u from local client to %s with %lu bytes\n", | ||
1845 | ntohl (crm->data_message->mid.mid), | ||
1846 | GCCH_2s (ch), | ||
1847 | (unsigned long) buf_len); | ||
1848 | if (NULL != ch->retry_data_task) | ||
1849 | { | ||
1850 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1851 | ch->retry_data_task = NULL; | ||
1852 | } | ||
1853 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1854 | &crm->data_message->ctn); | ||
1855 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1856 | return GNUNET_OK; | ||
1857 | } | ||
1858 | |||
1859 | |||
1860 | void | ||
1861 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
1862 | struct GNUNET_CADET_ClientChannelNumber client_ccn) | ||
1863 | { | ||
1864 | struct CadetChannelClient *ccc; | ||
1865 | struct CadetOutOfOrderMessage *com; | ||
1866 | |||
1867 | if ((NULL != ch->owner) && | ||
1868 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1869 | ccc = ch->owner; | ||
1870 | else if ((NULL != ch->dest) && | ||
1871 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1872 | ccc = ch->dest; | ||
1873 | else | ||
1874 | GNUNET_assert (0); | ||
1875 | ccc->client_ready = GNUNET_YES; | ||
1876 | com = ccc->head_recv; | ||
1877 | if (NULL == com) | ||
1878 | { | ||
1879 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1880 | "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n", | ||
1881 | GSC_2s (ccc->c), | ||
1882 | ntohl (client_ccn.channel_of_client), | ||
1883 | GCCH_2s (ch), | ||
1884 | ntohl (ccc->ccn.channel_of_client), | ||
1885 | ccc); | ||
1886 | return; /* none pending */ | ||
1887 | } | ||
1888 | if (GNUNET_YES == ch->is_loopback) | ||
1889 | { | ||
1890 | int to_owner; | ||
1891 | |||
1892 | /* Messages are always in-order, just send */ | ||
1893 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1894 | ccc->num_recv--; | ||
1895 | GSC_send_to_client (ccc->c, com->env); | ||
1896 | /* Notify sender that we can receive more */ | ||
1897 | if ((NULL != ch->owner) && | ||
1898 | (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1899 | { | ||
1900 | to_owner = GNUNET_NO; | ||
1901 | } | ||
1902 | else | ||
1903 | { | ||
1904 | GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client == | ||
1905 | ch->dest->ccn.channel_of_client)); | ||
1906 | to_owner = GNUNET_YES; | ||
1907 | } | ||
1908 | send_ack_to_client (ch, to_owner); | ||
1909 | GNUNET_free (com); | ||
1910 | return; | ||
1911 | } | ||
1912 | |||
1913 | if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) && | ||
1914 | (GNUNET_YES == ch->reliable)) | ||
1915 | { | ||
1916 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1917 | "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n", | ||
1918 | GSC_2s (ccc->c), | ||
1919 | ntohl (ccc->ccn.channel_of_client), | ||
1920 | ntohl (com->mid.mid), | ||
1921 | ntohl (ch->mid_recv.mid)); | ||
1922 | return; /* missing next one in-order */ | ||
1923 | } | ||
1924 | |||
1925 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1926 | "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n", | ||
1927 | ntohl (com->mid.mid), | ||
1928 | GSC_2s (ccc->c), | ||
1929 | ntohl (ccc->ccn.channel_of_client), | ||
1930 | GCCH_2s (ch)); | ||
1931 | |||
1932 | /* all good, pass next message to client */ | ||
1933 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1934 | ccc->num_recv--; | ||
1935 | /* FIXME: if unreliable, this is not aggressive | ||
1936 | enough, as it would be OK to have lost some! */ | ||
1937 | |||
1938 | ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid)); | ||
1939 | ch->mid_futures >>= 1; /* equivalent to division by 2 */ | ||
1940 | ccc->client_ready = GNUNET_NO; | ||
1941 | GSC_send_to_client (ccc->c, com->env); | ||
1942 | GNUNET_free (com); | ||
1943 | send_channel_data_ack (ch); | ||
1944 | if (NULL != ccc->head_recv) | ||
1945 | return; | ||
1946 | if (GNUNET_NO == ch->destroy) | ||
1947 | return; | ||
1948 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1949 | channel_destroy (ch); | ||
1950 | } | ||
1951 | |||
1952 | |||
1953 | #define LOG2(level, ...) \ | ||
1954 | GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__) | ||
1955 | |||
1956 | |||
1957 | /** | ||
1958 | * Log channel info. | ||
1959 | * | ||
1960 | * @param ch Channel. | ||
1961 | * @param level Debug level to use. | ||
1962 | */ | ||
1963 | void | ||
1964 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) | ||
1965 | { | ||
1966 | #if ! defined(GNUNET_CULL_LOGGING) | ||
1967 | int do_log; | ||
1968 | |||
1969 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1970 | "cadet-chn", | ||
1971 | __FILE__, | ||
1972 | __FUNCTION__, | ||
1973 | __LINE__); | ||
1974 | if (0 == do_log) | ||
1975 | return; | ||
1976 | |||
1977 | if (NULL == ch) | ||
1978 | { | ||
1979 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | ||
1980 | return; | ||
1981 | } | ||
1982 | LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch); | ||
1983 | if (NULL != ch->owner) | ||
1984 | { | ||
1985 | LOG2 (level, | ||
1986 | "CHN origin %s ready %s local-id: %u\n", | ||
1987 | GSC_2s (ch->owner->c), | ||
1988 | ch->owner->client_ready ? "YES" : "NO", | ||
1989 | ntohl (ch->owner->ccn.channel_of_client)); | ||
1990 | } | ||
1991 | if (NULL != ch->dest) | ||
1992 | { | ||
1993 | LOG2 (level, | ||
1994 | "CHN destination %s ready %s local-id: %u\n", | ||
1995 | GSC_2s (ch->dest->c), | ||
1996 | ch->dest->client_ready ? "YES" : "NO", | ||
1997 | ntohl (ch->dest->ccn.channel_of_client)); | ||
1998 | } | ||
1999 | LOG2 (level, | ||
2000 | "CHN Message IDs recv: %d (%llX), send: %d\n", | ||
2001 | ntohl (ch->mid_recv.mid), | ||
2002 | (unsigned long long) ch->mid_futures, | ||
2003 | ntohl (ch->mid_send.mid)); | ||
2004 | #endif | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* end of gnunet-service-cadet_channel.c */ | ||