diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_channel.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_channel.c | 2432 |
1 files changed, 2432 insertions, 0 deletions
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c new file mode 100644 index 000000000..91338d5c0 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_channel.c | |||
@@ -0,0 +1,2432 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | #include "platform.h" | ||
23 | #include "gnunet_util_lib.h" | ||
24 | |||
25 | #include "gnunet_statistics_service.h" | ||
26 | |||
27 | #include "cadet.h" | ||
28 | #include "cadet_protocol.h" | ||
29 | |||
30 | #include "gnunet-service-cadet_channel.h" | ||
31 | #include "gnunet-service-cadet_local.h" | ||
32 | #include "gnunet-service-cadet_tunnel.h" | ||
33 | #include "gnunet-service-cadet_peer.h" | ||
34 | |||
35 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__) | ||
36 | |||
37 | #define CADET_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\ | ||
38 | GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
39 | #define CADET_RETRANSMIT_MARGIN 4 | ||
40 | |||
41 | |||
42 | /** | ||
43 | * All the states a connection can be in. | ||
44 | */ | ||
45 | enum CadetChannelState | ||
46 | { | ||
47 | /** | ||
48 | * Uninitialized status, should never appear in operation. | ||
49 | */ | ||
50 | CADET_CHANNEL_NEW, | ||
51 | |||
52 | /** | ||
53 | * Connection create message sent, waiting for ACK. | ||
54 | */ | ||
55 | CADET_CHANNEL_SENT, | ||
56 | |||
57 | /** | ||
58 | * Connection confirmed, ready to carry traffic. | ||
59 | */ | ||
60 | CADET_CHANNEL_READY, | ||
61 | }; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Info holder for channel messages in queues. | ||
66 | */ | ||
67 | struct CadetChannelQueue | ||
68 | { | ||
69 | /** | ||
70 | * Tunnel Queue. | ||
71 | */ | ||
72 | struct CadetTunnel3Queue *tq; | ||
73 | |||
74 | /** | ||
75 | * Message type (DATA/DATA_ACK) | ||
76 | */ | ||
77 | uint16_t type; | ||
78 | |||
79 | /** | ||
80 | * Message copy (for DATAs, to start retransmission timer) | ||
81 | */ | ||
82 | struct CadetReliableMessage *copy; | ||
83 | |||
84 | /** | ||
85 | * Reliability (for DATA_ACKs, to access rel->ack_q) | ||
86 | */ | ||
87 | struct CadetChannelReliability *rel; | ||
88 | }; | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Info needed to retry a message in case it gets lost. | ||
93 | */ | ||
94 | struct CadetReliableMessage | ||
95 | { | ||
96 | /** | ||
97 | * Double linked list, FIFO style | ||
98 | */ | ||
99 | struct CadetReliableMessage *next; | ||
100 | struct CadetReliableMessage *prev; | ||
101 | |||
102 | /** | ||
103 | * Type of message (payload, channel management). | ||
104 | */ | ||
105 | int16_t type; | ||
106 | |||
107 | /** | ||
108 | * Tunnel Reliability queue this message is in. | ||
109 | */ | ||
110 | struct CadetChannelReliability *rel; | ||
111 | |||
112 | /** | ||
113 | * ID of the message (ACK needed to free) | ||
114 | */ | ||
115 | uint32_t mid; | ||
116 | |||
117 | /** | ||
118 | * Tunnel Queue. | ||
119 | */ | ||
120 | struct CadetChannelQueue *chq; | ||
121 | |||
122 | /** | ||
123 | * When was this message issued (to calculate ACK delay) | ||
124 | */ | ||
125 | struct GNUNET_TIME_Absolute timestamp; | ||
126 | |||
127 | /* struct GNUNET_CADET_Data with payload */ | ||
128 | }; | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Info about the traffic state for a client in a channel. | ||
133 | */ | ||
134 | struct CadetChannelReliability | ||
135 | { | ||
136 | /** | ||
137 | * Channel this is about. | ||
138 | */ | ||
139 | struct CadetChannel *ch; | ||
140 | |||
141 | /** | ||
142 | * DLL of messages sent and not yet ACK'd. | ||
143 | */ | ||
144 | struct CadetReliableMessage *head_sent; | ||
145 | struct CadetReliableMessage *tail_sent; | ||
146 | |||
147 | /** | ||
148 | * DLL of messages received out of order. | ||
149 | */ | ||
150 | struct CadetReliableMessage *head_recv; | ||
151 | struct CadetReliableMessage *tail_recv; | ||
152 | |||
153 | /** | ||
154 | * Messages received. | ||
155 | */ | ||
156 | unsigned int n_recv; | ||
157 | |||
158 | /** | ||
159 | * Next MID to use for outgoing traffic. | ||
160 | */ | ||
161 | uint32_t mid_send; | ||
162 | |||
163 | /** | ||
164 | * Next MID expected for incoming traffic. | ||
165 | */ | ||
166 | uint32_t mid_recv; | ||
167 | |||
168 | /** | ||
169 | * Handle for queued unique data CREATE, DATA_ACK. | ||
170 | */ | ||
171 | struct CadetChannelQueue *uniq; | ||
172 | |||
173 | /** | ||
174 | * Can we send data to the client? | ||
175 | */ | ||
176 | int client_ready; | ||
177 | |||
178 | /** | ||
179 | * Can the client send data to us? | ||
180 | */ | ||
181 | int client_allowed; | ||
182 | |||
183 | /** | ||
184 | * Task to resend/poll in case no ACK is received. | ||
185 | */ | ||
186 | GNUNET_SCHEDULER_TaskIdentifier retry_task; | ||
187 | |||
188 | /** | ||
189 | * Counter for exponential backoff. | ||
190 | */ | ||
191 | struct GNUNET_TIME_Relative retry_timer; | ||
192 | |||
193 | /** | ||
194 | * How long does it usually take to get an ACK. | ||
195 | */ | ||
196 | struct GNUNET_TIME_Relative expected_delay; | ||
197 | }; | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Struct containing all information regarding a channel to a remote client. | ||
202 | */ | ||
203 | struct CadetChannel | ||
204 | { | ||
205 | /** | ||
206 | * Tunnel this channel is in. | ||
207 | */ | ||
208 | struct CadetTunnel3 *t; | ||
209 | |||
210 | /** | ||
211 | * Destination port of the channel. | ||
212 | */ | ||
213 | uint32_t port; | ||
214 | |||
215 | /** | ||
216 | * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
217 | */ | ||
218 | CADET_ChannelNumber gid; | ||
219 | |||
220 | /** | ||
221 | * Local tunnel number for root (owner) client. | ||
222 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 ) | ||
223 | */ | ||
224 | CADET_ChannelNumber lid_root; | ||
225 | |||
226 | /** | ||
227 | * Local tunnel number for local destination clients (incoming number) | ||
228 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0). | ||
229 | */ | ||
230 | CADET_ChannelNumber lid_dest; | ||
231 | |||
232 | /** | ||
233 | * Channel state. | ||
234 | */ | ||
235 | enum CadetChannelState state; | ||
236 | |||
237 | /** | ||
238 | * Is the tunnel bufferless (minimum latency)? | ||
239 | */ | ||
240 | int nobuffer; | ||
241 | |||
242 | /** | ||
243 | * Is the tunnel reliable? | ||
244 | */ | ||
245 | int reliable; | ||
246 | |||
247 | /** | ||
248 | * Last time the channel was used | ||
249 | */ | ||
250 | struct GNUNET_TIME_Absolute timestamp; | ||
251 | |||
252 | /** | ||
253 | * Client owner of the tunnel, if any | ||
254 | */ | ||
255 | struct CadetClient *root; | ||
256 | |||
257 | /** | ||
258 | * Client destination of the tunnel, if any. | ||
259 | */ | ||
260 | struct CadetClient *dest; | ||
261 | |||
262 | /** | ||
263 | * Flag to signal the destruction of the channel. | ||
264 | * If this is set GNUNET_YES the channel will be destroyed | ||
265 | * when the queue is empty. | ||
266 | */ | ||
267 | int destroy; | ||
268 | |||
269 | /** | ||
270 | * Total (reliable) messages pending ACK for this channel. | ||
271 | */ | ||
272 | unsigned int pending_messages; | ||
273 | |||
274 | /** | ||
275 | * Reliability data. | ||
276 | * Only present (non-NULL) at the owner of a tunnel. | ||
277 | */ | ||
278 | struct CadetChannelReliability *root_rel; | ||
279 | |||
280 | /** | ||
281 | * Reliability data. | ||
282 | * Only present (non-NULL) at the destination of a tunnel. | ||
283 | */ | ||
284 | struct CadetChannelReliability *dest_rel; | ||
285 | |||
286 | }; | ||
287 | |||
288 | |||
289 | /******************************************************************************/ | ||
290 | /******************************* GLOBALS ***********************************/ | ||
291 | /******************************************************************************/ | ||
292 | |||
293 | /** | ||
294 | * Global handle to the statistics service. | ||
295 | */ | ||
296 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
297 | |||
298 | /** | ||
299 | * Local peer own ID (memory efficient handle). | ||
300 | */ | ||
301 | extern GNUNET_PEER_Id myid; | ||
302 | |||
303 | |||
304 | /******************************************************************************/ | ||
305 | /******************************** STATIC ***********************************/ | ||
306 | /******************************************************************************/ | ||
307 | |||
308 | /** | ||
309 | * Destroy a reliable message after it has been acknowledged, either by | ||
310 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
311 | * timers and frees all memory. | ||
312 | * | ||
313 | * @param copy Message that is no longer needed: remote peer got it. | ||
314 | * @param update_time Is the timing information relevant? | ||
315 | * If this message is ACK in a batch the timing information | ||
316 | * is skewed by the retransmission, count only for the | ||
317 | * retransmitted message. | ||
318 | */ | ||
319 | static int | ||
320 | rel_message_free (struct CadetReliableMessage *copy, int update_time); | ||
321 | |||
322 | /** | ||
323 | * send a channel create message. | ||
324 | * | ||
325 | * @param ch Channel for which to send. | ||
326 | */ | ||
327 | static void | ||
328 | send_create (struct CadetChannel *ch); | ||
329 | |||
330 | /** | ||
331 | * Confirm we got a channel create, FWD ack. | ||
332 | * | ||
333 | * @param ch The channel to confirm. | ||
334 | * @param fwd Should we send a FWD ACK? (going dest->root) | ||
335 | * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. | ||
336 | */ | ||
337 | static void | ||
338 | send_ack (struct CadetChannel *ch, int fwd, int reaction); | ||
339 | |||
340 | |||
341 | |||
342 | /** | ||
343 | * Test if the channel is loopback: both root and dest are on the local peer. | ||
344 | * | ||
345 | * @param ch Channel to test. | ||
346 | * | ||
347 | * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise. | ||
348 | */ | ||
349 | static int | ||
350 | is_loopback (const struct CadetChannel *ch) | ||
351 | { | ||
352 | if (NULL != ch->t) | ||
353 | return GMT_is_loopback (ch->t); | ||
354 | |||
355 | return (NULL != ch->root && NULL != ch->dest); | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Save a copy of the data message for later retransmission. | ||
361 | * | ||
362 | * @param msg Message to copy. | ||
363 | * @param mid Message ID. | ||
364 | * @param rel Reliability data for retransmission. | ||
365 | */ | ||
366 | static struct CadetReliableMessage * | ||
367 | copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid, | ||
368 | struct CadetChannelReliability *rel) | ||
369 | { | ||
370 | struct CadetReliableMessage *copy; | ||
371 | uint16_t size; | ||
372 | |||
373 | size = ntohs (msg->header.size); | ||
374 | copy = GNUNET_malloc (sizeof (*copy) + size); | ||
375 | copy->mid = mid; | ||
376 | copy->rel = rel; | ||
377 | copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA; | ||
378 | memcpy (©[1], msg, size); | ||
379 | |||
380 | return copy; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * We have received a message out of order, or the client is not ready. | ||
385 | * Buffer it until we receive an ACK from the client or the missing | ||
386 | * message from the channel. | ||
387 | * | ||
388 | * @param msg Message to buffer (MUST be of type CADET_DATA). | ||
389 | * @param rel Reliability data to the corresponding direction. | ||
390 | */ | ||
391 | static void | ||
392 | add_buffered_data (const struct GNUNET_CADET_Data *msg, | ||
393 | struct CadetChannelReliability *rel) | ||
394 | { | ||
395 | struct CadetReliableMessage *copy; | ||
396 | struct CadetReliableMessage *prev; | ||
397 | uint32_t mid; | ||
398 | |||
399 | mid = ntohl (msg->mid); | ||
400 | |||
401 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid); | ||
402 | |||
403 | rel->n_recv++; | ||
404 | |||
405 | // FIXME do something better than O(n), although n < 64... | ||
406 | // FIXME start from the end (most messages are the latest ones) | ||
407 | for (prev = rel->head_recv; NULL != prev; prev = prev->next) | ||
408 | { | ||
409 | LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid); | ||
410 | if (prev->mid == mid) | ||
411 | { | ||
412 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n"); | ||
413 | return; | ||
414 | } | ||
415 | else if (GM_is_pid_bigger (prev->mid, mid)) | ||
416 | { | ||
417 | LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n"); | ||
418 | copy = copy_message (msg, mid, rel); | ||
419 | GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv, | ||
420 | prev, copy); | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | copy = copy_message (msg, mid, rel); | ||
425 | LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n"); | ||
426 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy); | ||
427 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n"); | ||
428 | } | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Add a destination client to a channel, initializing all data structures | ||
433 | * in the channel and the client. | ||
434 | * | ||
435 | * @param ch Channel to which add the destination. | ||
436 | * @param c Client which to add to the channel. | ||
437 | */ | ||
438 | static void | ||
439 | add_destination (struct CadetChannel *ch, struct CadetClient *c) | ||
440 | { | ||
441 | if (NULL != ch->dest) | ||
442 | { | ||
443 | GNUNET_break (0); | ||
444 | return; | ||
445 | } | ||
446 | |||
447 | /* Assign local id as destination */ | ||
448 | ch->lid_dest = GML_get_next_chid (c); | ||
449 | |||
450 | /* Store in client's hashmap */ | ||
451 | GML_channel_add (c, ch->lid_dest, ch); | ||
452 | |||
453 | GNUNET_break (NULL == ch->dest_rel); | ||
454 | ch->dest_rel = GNUNET_new (struct CadetChannelReliability); | ||
455 | ch->dest_rel->ch = ch; | ||
456 | ch->dest_rel->expected_delay.rel_value_us = 0; | ||
457 | ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
458 | |||
459 | ch->dest = c; | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Set options in a channel, extracted from a bit flag field. | ||
465 | * | ||
466 | * @param ch Channel to set options to. | ||
467 | * @param options Bit array in host byte order. | ||
468 | */ | ||
469 | static void | ||
470 | channel_set_options (struct CadetChannel *ch, uint32_t options) | ||
471 | { | ||
472 | ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ? | ||
473 | GNUNET_YES : GNUNET_NO; | ||
474 | ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ? | ||
475 | GNUNET_YES : GNUNET_NO; | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Get a bit flag field with the options of a channel. | ||
481 | * | ||
482 | * @param ch Channel to get options from. | ||
483 | * | ||
484 | * @return Bit array in host byte order. | ||
485 | */ | ||
486 | static uint32_t | ||
487 | channel_get_options (struct CadetChannel *ch) | ||
488 | { | ||
489 | uint32_t options; | ||
490 | |||
491 | options = 0; | ||
492 | if (ch->nobuffer) | ||
493 | options |= GNUNET_CADET_OPTION_NOBUFFER; | ||
494 | if (ch->reliable) | ||
495 | options |= GNUNET_CADET_OPTION_RELIABLE; | ||
496 | |||
497 | return options; | ||
498 | } | ||
499 | |||
500 | |||
501 | /** | ||
502 | * Notify a client that the channel is no longer valid. | ||
503 | * | ||
504 | * @param ch Channel that is destroyed. | ||
505 | * @param local_only Should we avoid sending it to other peers? | ||
506 | */ | ||
507 | static void | ||
508 | send_destroy (struct CadetChannel *ch, int local_only) | ||
509 | { | ||
510 | struct GNUNET_CADET_ChannelManage msg; | ||
511 | |||
512 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
513 | msg.header.size = htons (sizeof (msg)); | ||
514 | msg.chid = htonl (ch->gid); | ||
515 | |||
516 | /* If root is not NULL, notify. | ||
517 | * If it's NULL, check lid_root. When a local destroy comes in, root | ||
518 | * is set to NULL but lid_root is left untouched. In this case, do nothing, | ||
519 | * the client is the one who requested the channel to be destroyed. | ||
520 | */ | ||
521 | if (NULL != ch->root) | ||
522 | GML_send_channel_destroy (ch->root, ch->lid_root); | ||
523 | else if (0 == ch->lid_root && GNUNET_NO == local_only) | ||
524 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
525 | |||
526 | if (NULL != ch->dest) | ||
527 | GML_send_channel_destroy (ch->dest, ch->lid_dest); | ||
528 | else if (0 == ch->lid_dest && GNUNET_NO == local_only) | ||
529 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL); | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Notify the destination client that a new incoming channel was created. | ||
535 | * | ||
536 | * @param ch Channel that was created. | ||
537 | */ | ||
538 | static void | ||
539 | send_client_create (struct CadetChannel *ch) | ||
540 | { | ||
541 | uint32_t opt; | ||
542 | |||
543 | if (NULL == ch->dest) | ||
544 | return; | ||
545 | |||
546 | opt = 0; | ||
547 | opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0; | ||
548 | opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0; | ||
549 | GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt, | ||
550 | GMT_get_destination (ch->t)); | ||
551 | |||
552 | } | ||
553 | |||
554 | |||
555 | /** | ||
556 | * Send data to a client. | ||
557 | * | ||
558 | * If the client is ready, send directly, otherwise buffer while listening | ||
559 | * for a local ACK. | ||
560 | * | ||
561 | * @param ch Channel | ||
562 | * @param msg Message. | ||
563 | * @param fwd Is this a fwd (root->dest) message? | ||
564 | */ | ||
565 | static void | ||
566 | send_client_data (struct CadetChannel *ch, | ||
567 | const struct GNUNET_CADET_Data *msg, | ||
568 | int fwd) | ||
569 | { | ||
570 | if (fwd) | ||
571 | { | ||
572 | if (ch->dest_rel->client_ready) | ||
573 | GML_send_data (ch->dest, msg, ch->lid_dest); | ||
574 | else | ||
575 | add_buffered_data (msg, ch->dest_rel); | ||
576 | } | ||
577 | else | ||
578 | { | ||
579 | if (ch->root_rel->client_ready) | ||
580 | GML_send_data (ch->root, msg, ch->lid_root); | ||
581 | else | ||
582 | add_buffered_data (msg, ch->root_rel); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | |||
587 | /** | ||
588 | * Send a buffered message to the client, for in order delivery or | ||
589 | * as result of client ACK. | ||
590 | * | ||
591 | * @param ch Channel on which to empty the message buffer. | ||
592 | * @param c Client to send to. | ||
593 | * @param fwd Is this to send FWD data?. | ||
594 | */ | ||
595 | static void | ||
596 | send_client_buffered_data (struct CadetChannel *ch, | ||
597 | struct CadetClient *c, | ||
598 | int fwd) | ||
599 | { | ||
600 | struct CadetReliableMessage *copy; | ||
601 | struct CadetChannelReliability *rel; | ||
602 | |||
603 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n"); | ||
604 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
605 | if (GNUNET_NO == rel->client_ready) | ||
606 | { | ||
607 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n"); | ||
608 | return; | ||
609 | } | ||
610 | |||
611 | copy = rel->head_recv; | ||
612 | /* We never buffer channel management messages */ | ||
613 | if (NULL != copy) | ||
614 | { | ||
615 | if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) | ||
616 | { | ||
617 | struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) ©[1]; | ||
618 | |||
619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | " have %u! now expecting %u\n", | ||
621 | copy->mid, rel->mid_recv + 1); | ||
622 | send_client_data (ch, msg, fwd); | ||
623 | rel->n_recv--; | ||
624 | rel->mid_recv++; | ||
625 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | ||
626 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE RECV %p\n", copy); | ||
627 | GNUNET_free (copy); | ||
628 | } | ||
629 | else | ||
630 | { | ||
631 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
632 | " reliable && don't have %u, next is %u\n", | ||
633 | rel->mid_recv, | ||
634 | copy->mid); | ||
635 | if (GNUNET_YES == ch->destroy) | ||
636 | { | ||
637 | /* We don't have the next data piece and the remote peer has closed the | ||
638 | * channel. We won't receive it anymore, so just destroy the channel. | ||
639 | * FIXME: wait some time to allow other connections to | ||
640 | * deliver missing messages | ||
641 | */ | ||
642 | send_destroy (ch, GNUNET_YES); | ||
643 | GMCH_destroy (ch); | ||
644 | } | ||
645 | } | ||
646 | } | ||
647 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n"); | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Allow a client to send more data. | ||
653 | * | ||
654 | * In case the client was already allowed to send data, do nothing. | ||
655 | * | ||
656 | * @param ch Channel. | ||
657 | * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root) | ||
658 | */ | ||
659 | static void | ||
660 | send_client_ack (struct CadetChannel *ch, int fwd) | ||
661 | { | ||
662 | struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel; | ||
663 | struct CadetClient *c = fwd ? ch->root : ch->dest; | ||
664 | |||
665 | if (NULL == c) | ||
666 | { | ||
667 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
668 | return; | ||
669 | } | ||
670 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
671 | " sending %s ack to client on channel %s\n", | ||
672 | GM_f2s (fwd), GMCH_2s (ch)); | ||
673 | |||
674 | if (NULL == rel) | ||
675 | { | ||
676 | GNUNET_break (0); | ||
677 | return; | ||
678 | } | ||
679 | |||
680 | if (GNUNET_YES == rel->client_allowed) | ||
681 | { | ||
682 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n"); | ||
683 | return; | ||
684 | } | ||
685 | rel->client_allowed = GNUNET_YES; | ||
686 | |||
687 | GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest); | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Notify the root that the destination rejected the channel. | ||
693 | * | ||
694 | * @param ch Rejected channel. | ||
695 | */ | ||
696 | static void | ||
697 | send_client_nack (struct CadetChannel *ch) | ||
698 | { | ||
699 | if (NULL == ch->root) | ||
700 | { | ||
701 | GNUNET_break (0); | ||
702 | return; | ||
703 | } | ||
704 | GML_send_channel_nack (ch->root, ch->lid_root); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * We haven't received an ACK after a certain time: restransmit the message. | ||
710 | * | ||
711 | * @param cls Closure (CadetChannelReliability with the message to restransmit) | ||
712 | * @param tc TaskContext. | ||
713 | */ | ||
714 | static void | ||
715 | channel_retransmit_message (void *cls, | ||
716 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
717 | { | ||
718 | struct CadetChannelReliability *rel = cls; | ||
719 | struct CadetReliableMessage *copy; | ||
720 | struct CadetChannel *ch; | ||
721 | struct GNUNET_CADET_Data *payload; | ||
722 | int fwd; | ||
723 | |||
724 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
725 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
726 | return; | ||
727 | |||
728 | ch = rel->ch; | ||
729 | copy = rel->head_sent; | ||
730 | if (NULL == copy) | ||
731 | { | ||
732 | GNUNET_break (0); | ||
733 | return; | ||
734 | } | ||
735 | |||
736 | payload = (struct GNUNET_CADET_Data *) ©[1]; | ||
737 | fwd = (rel == ch->root_rel); | ||
738 | |||
739 | /* Message not found in the queue that we are going to use. */ | ||
740 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid); | ||
741 | |||
742 | GMCH_send_prebuilt_message (&payload->header, ch, fwd, copy); | ||
743 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | ||
744 | } | ||
745 | |||
746 | |||
747 | /** | ||
748 | * We haven't received an Channel ACK after a certain time: resend the CREATE. | ||
749 | * | ||
750 | * @param cls Closure (CadetChannelReliability of the channel to recreate) | ||
751 | * @param tc TaskContext. | ||
752 | */ | ||
753 | static void | ||
754 | channel_recreate (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
755 | { | ||
756 | struct CadetChannelReliability *rel = cls; | ||
757 | |||
758 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
759 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
760 | return; | ||
761 | |||
762 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RE-CREATE\n"); | ||
763 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | ||
764 | |||
765 | if (rel == rel->ch->root_rel) | ||
766 | { | ||
767 | send_create (rel->ch); | ||
768 | } | ||
769 | else if (rel == rel->ch->dest_rel) | ||
770 | { | ||
771 | send_ack (rel->ch, GNUNET_YES, GNUNET_NO); | ||
772 | } | ||
773 | else | ||
774 | { | ||
775 | GNUNET_break (0); | ||
776 | } | ||
777 | |||
778 | } | ||
779 | |||
780 | |||
781 | /** | ||
782 | * Message has been sent: start retransmission timer. | ||
783 | * | ||
784 | * @param cls Closure (queue structure). | ||
785 | * @param t Tunnel. | ||
786 | * @param q Queue handler (no longer valid). | ||
787 | * @param type Type of message. | ||
788 | * @param size Size of the message. | ||
789 | */ | ||
790 | static void | ||
791 | ch_message_sent (void *cls, | ||
792 | struct CadetTunnel3 *t, | ||
793 | struct CadetTunnel3Queue *q, | ||
794 | uint16_t type, size_t size) | ||
795 | { | ||
796 | struct CadetChannelQueue *chq = cls; | ||
797 | struct CadetReliableMessage *copy = chq->copy; | ||
798 | struct CadetChannelReliability *rel; | ||
799 | |||
800 | LOG (GNUNET_ERROR_TYPE_DEBUG, "channel message sent callback %s\n", | ||
801 | GM_m2s (chq->type)); | ||
802 | |||
803 | switch (chq->type) | ||
804 | { | ||
805 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
806 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT DATA MID %u\n", copy->mid); | ||
807 | GNUNET_assert (chq == copy->chq); | ||
808 | copy->timestamp = GNUNET_TIME_absolute_get (); | ||
809 | rel = copy->rel; | ||
810 | if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task) | ||
811 | { | ||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! scheduling retry in 4 * %s\n", | ||
813 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
814 | GNUNET_YES)); | ||
815 | if (0 != rel->expected_delay.rel_value_us) | ||
816 | { | ||
817 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay != 0\n"); | ||
818 | rel->retry_timer = | ||
819 | GNUNET_TIME_relative_multiply (rel->expected_delay, | ||
820 | CADET_RETRANSMIT_MARGIN); | ||
821 | } | ||
822 | else | ||
823 | { | ||
824 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay reset\n"); | ||
825 | rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
826 | } | ||
827 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! using delay %s\n", | ||
828 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
829 | GNUNET_NO)); | ||
830 | rel->retry_task = | ||
831 | GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
832 | &channel_retransmit_message, rel); | ||
833 | } | ||
834 | else | ||
835 | { | ||
836 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! retry task %u\n", rel->retry_task); | ||
837 | } | ||
838 | copy->chq = NULL; | ||
839 | break; | ||
840 | |||
841 | |||
842 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
843 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
844 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
845 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT %s\n", GM_m2s (chq->type)); | ||
846 | rel = chq->rel; | ||
847 | GNUNET_assert (rel->uniq == chq); | ||
848 | rel->uniq = NULL; | ||
849 | |||
850 | if (CADET_CHANNEL_READY != rel->ch->state | ||
851 | && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type | ||
852 | && GNUNET_NO == rel->ch->destroy) | ||
853 | { | ||
854 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rel->retry_task); | ||
855 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! STD BACKOFF %s\n", | ||
856 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
857 | GNUNET_NO)); | ||
858 | rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer); | ||
859 | rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
860 | &channel_recreate, rel); | ||
861 | } | ||
862 | break; | ||
863 | |||
864 | default: | ||
865 | GNUNET_break (0); | ||
866 | } | ||
867 | |||
868 | GNUNET_free (chq); | ||
869 | } | ||
870 | |||
871 | |||
872 | /** | ||
873 | * send a channel create message. | ||
874 | * | ||
875 | * @param ch Channel for which to send. | ||
876 | */ | ||
877 | static void | ||
878 | send_create (struct CadetChannel *ch) | ||
879 | { | ||
880 | struct GNUNET_CADET_ChannelCreate msgcc; | ||
881 | |||
882 | msgcc.header.size = htons (sizeof (msgcc)); | ||
883 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); | ||
884 | msgcc.chid = htonl (ch->gid); | ||
885 | msgcc.port = htonl (ch->port); | ||
886 | msgcc.opt = htonl (channel_get_options (ch)); | ||
887 | |||
888 | GMCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL); | ||
889 | } | ||
890 | |||
891 | |||
892 | /** | ||
893 | * Confirm we got a channel create or FWD ack. | ||
894 | * | ||
895 | * @param ch The channel to confirm. | ||
896 | * @param fwd Should we send a FWD ACK? (going dest->root) | ||
897 | * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. | ||
898 | */ | ||
899 | static void | ||
900 | send_ack (struct CadetChannel *ch, int fwd, int reaction) | ||
901 | { | ||
902 | struct GNUNET_CADET_ChannelManage msg; | ||
903 | |||
904 | msg.header.size = htons (sizeof (msg)); | ||
905 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK); | ||
906 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending channel %s ack for channel %s\n", | ||
907 | GM_f2s (fwd), GMCH_2s (ch)); | ||
908 | |||
909 | msg.chid = htonl (ch->gid); | ||
910 | GMCH_send_prebuilt_message (&msg.header, ch, !fwd, reaction ? &msg : NULL); | ||
911 | } | ||
912 | |||
913 | |||
914 | /** | ||
915 | * Send a message and don't keep any info about it: we won't need to cancel it | ||
916 | * or resend it. | ||
917 | * | ||
918 | * @param msg Header of the message to fire away. | ||
919 | * @param ch Channel on which the message should go. | ||
920 | * @param force Is this a forced (undroppable) message? | ||
921 | */ | ||
922 | static void | ||
923 | fire_and_forget (const struct GNUNET_MessageHeader *msg, | ||
924 | struct CadetChannel *ch, | ||
925 | int force) | ||
926 | { | ||
927 | GNUNET_break (NULL == GMT_send_prebuilt_message (msg, ch->t, NULL, | ||
928 | force, NULL, NULL)); | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Notify that a channel create didn't succeed. | ||
934 | * | ||
935 | * @param ch The channel to reject. | ||
936 | */ | ||
937 | static void | ||
938 | send_nack (struct CadetChannel *ch) | ||
939 | { | ||
940 | struct GNUNET_CADET_ChannelManage msg; | ||
941 | |||
942 | msg.header.size = htons (sizeof (msg)); | ||
943 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK); | ||
944 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
945 | " sending channel NACK for channel %s\n", | ||
946 | GMCH_2s (ch)); | ||
947 | |||
948 | msg.chid = htonl (ch->gid); | ||
949 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
950 | } | ||
951 | |||
952 | |||
953 | /** | ||
954 | * Destroy all reliable messages queued for a channel, | ||
955 | * during a channel destruction. | ||
956 | * Frees the reliability structure itself. | ||
957 | * | ||
958 | * @param rel Reliability data for a channel. | ||
959 | */ | ||
960 | static void | ||
961 | channel_rel_free_all (struct CadetChannelReliability *rel) | ||
962 | { | ||
963 | struct CadetReliableMessage *copy; | ||
964 | struct CadetReliableMessage *next; | ||
965 | |||
966 | if (NULL == rel) | ||
967 | return; | ||
968 | |||
969 | for (copy = rel->head_recv; NULL != copy; copy = next) | ||
970 | { | ||
971 | next = copy->next; | ||
972 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | ||
973 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH RECV %p\n", copy); | ||
974 | GNUNET_break (NULL == copy->chq); | ||
975 | GNUNET_free (copy); | ||
976 | } | ||
977 | for (copy = rel->head_sent; NULL != copy; copy = next) | ||
978 | { | ||
979 | next = copy->next; | ||
980 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
981 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH %p\n", copy); | ||
982 | if (NULL != copy->chq) | ||
983 | { | ||
984 | if (NULL != copy->chq->tq) | ||
985 | { | ||
986 | GMT_cancel (copy->chq->tq); | ||
987 | /* ch_message_sent will free copy->q */ | ||
988 | } | ||
989 | else | ||
990 | { | ||
991 | GNUNET_free (copy->chq); | ||
992 | GNUNET_break (0); | ||
993 | } | ||
994 | } | ||
995 | GNUNET_free (copy); | ||
996 | } | ||
997 | if (NULL != rel->uniq && NULL != rel->uniq->tq) | ||
998 | { | ||
999 | GMT_cancel (rel->uniq->tq); | ||
1000 | /* ch_message_sent is called freeing uniq */ | ||
1001 | } | ||
1002 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
1003 | { | ||
1004 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
1005 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
1006 | } | ||
1007 | GNUNET_free (rel); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /** | ||
1012 | * Mark future messages as ACK'd. | ||
1013 | * | ||
1014 | * @param rel Reliability data. | ||
1015 | * @param msg DataACK message with a bitfield of future ACK'd messages. | ||
1016 | */ | ||
1017 | static void | ||
1018 | channel_rel_free_sent (struct CadetChannelReliability *rel, | ||
1019 | const struct GNUNET_CADET_DataACK *msg) | ||
1020 | { | ||
1021 | struct CadetReliableMessage *copy; | ||
1022 | struct CadetReliableMessage *next; | ||
1023 | uint64_t bitfield; | ||
1024 | uint64_t mask; | ||
1025 | uint32_t mid; | ||
1026 | uint32_t target; | ||
1027 | unsigned int i; | ||
1028 | |||
1029 | bitfield = msg->futures; | ||
1030 | mid = ntohl (msg->mid); | ||
1031 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1032 | "!!! free_sent_reliable %u %llX\n", | ||
1033 | mid, bitfield); | ||
1034 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1035 | " rel %p, head %p\n", | ||
1036 | rel, rel->head_sent); | ||
1037 | for (i = 0, copy = rel->head_sent; | ||
1038 | i < 64 && NULL != copy && 0 != bitfield; | ||
1039 | i++) | ||
1040 | { | ||
1041 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1042 | " trying bit %u (mid %u)\n", | ||
1043 | i, mid + i + 1); | ||
1044 | mask = 0x1LL << i; | ||
1045 | if (0 == (bitfield & mask)) | ||
1046 | continue; | ||
1047 | |||
1048 | LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n"); | ||
1049 | /* Bit was set, clear the bit from the bitfield */ | ||
1050 | bitfield &= ~mask; | ||
1051 | |||
1052 | /* The i-th bit was set. Do we have that copy? */ | ||
1053 | /* Skip copies with mid < target */ | ||
1054 | target = mid + i + 1; | ||
1055 | LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target); | ||
1056 | while (NULL != copy && GM_is_pid_bigger (target, copy->mid)) | ||
1057 | copy = copy->next; | ||
1058 | |||
1059 | /* Did we run out of copies? (previously freed, it's ok) */ | ||
1060 | if (NULL == copy) | ||
1061 | { | ||
1062 | LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n"); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | /* Did we overshoot the target? (previously freed, it's ok) */ | ||
1067 | if (GM_is_pid_bigger (copy->mid, target)) | ||
1068 | { | ||
1069 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid); | ||
1070 | continue; | ||
1071 | } | ||
1072 | |||
1073 | /* Now copy->mid == target, free it */ | ||
1074 | next = copy->next; | ||
1075 | GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES)); | ||
1076 | copy = next; | ||
1077 | } | ||
1078 | LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n"); | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
1083 | * Destroy a reliable message after it has been acknowledged, either by | ||
1084 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
1085 | * timers and frees all memory. | ||
1086 | * | ||
1087 | * @param copy Message that is no longer needed: remote peer got it. | ||
1088 | * @param update_time Is the timing information relevant? | ||
1089 | * If this message is ACK in a batch the timing information | ||
1090 | * is skewed by the retransmission, count only for the | ||
1091 | * retransmitted message. | ||
1092 | * | ||
1093 | * @return #GNUNET_YES if channel was destroyed as a result of the call, | ||
1094 | * #GNUNET_NO otherwise. | ||
1095 | */ | ||
1096 | static int | ||
1097 | rel_message_free (struct CadetReliableMessage *copy, int update_time) | ||
1098 | { | ||
1099 | struct CadetChannelReliability *rel; | ||
1100 | struct GNUNET_TIME_Relative time; | ||
1101 | |||
1102 | rel = copy->rel; | ||
1103 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid); | ||
1104 | if (update_time) | ||
1105 | { | ||
1106 | time = GNUNET_TIME_absolute_get_duration (copy->timestamp); | ||
1107 | if (0 == rel->expected_delay.rel_value_us) | ||
1108 | rel->expected_delay = time; | ||
1109 | else | ||
1110 | { | ||
1111 | rel->expected_delay.rel_value_us *= 7; | ||
1112 | rel->expected_delay.rel_value_us += time.rel_value_us; | ||
1113 | rel->expected_delay.rel_value_us /= 8; | ||
1114 | } | ||
1115 | LOG (GNUNET_ERROR_TYPE_INFO, "!!! took %s, new delay %s\n", | ||
1116 | GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO), | ||
1117 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
1118 | GNUNET_NO)); | ||
1119 | rel->retry_timer = rel->expected_delay; | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | LOG (GNUNET_ERROR_TYPE_INFO, "!!! batch free, ignoring timing\n"); | ||
1124 | } | ||
1125 | rel->ch->pending_messages--; | ||
1126 | if (NULL != copy->chq) | ||
1127 | { | ||
1128 | GMT_cancel (copy->chq->tq); | ||
1129 | /* copy->q is set to NULL by ch_message_sent */ | ||
1130 | } | ||
1131 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
1132 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE %p\n", copy); | ||
1133 | GNUNET_free (copy); | ||
1134 | |||
1135 | if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages) | ||
1136 | { | ||
1137 | GMCH_destroy (rel->ch); | ||
1138 | return GNUNET_YES; | ||
1139 | } | ||
1140 | return GNUNET_NO; | ||
1141 | } | ||
1142 | |||
1143 | |||
1144 | /** | ||
1145 | * Channel was ACK'd by remote peer, mark as ready and cancel retransmission. | ||
1146 | * | ||
1147 | * @param ch Channel to mark as ready. | ||
1148 | * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK) | ||
1149 | */ | ||
1150 | static void | ||
1151 | channel_confirm (struct CadetChannel *ch, int fwd) | ||
1152 | { | ||
1153 | struct CadetChannelReliability *rel; | ||
1154 | enum CadetChannelState oldstate; | ||
1155 | |||
1156 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1157 | if (NULL == rel) | ||
1158 | { | ||
1159 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1160 | return; | ||
1161 | } | ||
1162 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n", | ||
1163 | GM_f2s (fwd), GMCH_2s (ch)); | ||
1164 | oldstate = ch->state; | ||
1165 | ch->state = CADET_CHANNEL_READY; | ||
1166 | |||
1167 | if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch)) | ||
1168 | { | ||
1169 | rel->client_ready = GNUNET_YES; | ||
1170 | rel->expected_delay = rel->retry_timer; | ||
1171 | LOG (GNUNET_ERROR_TYPE_DEBUG, " !! retry timer confirm %s\n", | ||
1172 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); | ||
1173 | if (GMT_get_connections_buffer (ch->t) > 0 || GMT_is_loopback (ch->t)) | ||
1174 | send_client_ack (ch, fwd); | ||
1175 | |||
1176 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
1177 | { | ||
1178 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
1179 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
1180 | } | ||
1181 | else if (NULL != rel->uniq) | ||
1182 | { | ||
1183 | GMT_cancel (rel->uniq->tq); | ||
1184 | /* ch_message_sent will free and NULL uniq */ | ||
1185 | } | ||
1186 | else | ||
1187 | { | ||
1188 | if (GNUNET_NO == is_loopback (ch)) | ||
1189 | { | ||
1190 | /* We SHOULD have been trying to retransmit this! */ | ||
1191 | GNUNET_break (0); | ||
1192 | } | ||
1193 | } | ||
1194 | } | ||
1195 | |||
1196 | /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */ | ||
1197 | if (GNUNET_YES == fwd) | ||
1198 | send_ack (ch, GNUNET_NO, GNUNET_NO); | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Save a copy to retransmit in case it gets lost. | ||
1204 | * | ||
1205 | * Initializes all needed callbacks and timers. | ||
1206 | * | ||
1207 | * @param ch Channel this message goes on. | ||
1208 | * @param msg Message to copy. | ||
1209 | * @param fwd Is this fwd traffic? | ||
1210 | */ | ||
1211 | static struct CadetReliableMessage * | ||
1212 | channel_save_copy (struct CadetChannel *ch, | ||
1213 | const struct GNUNET_MessageHeader *msg, | ||
1214 | int fwd) | ||
1215 | { | ||
1216 | struct CadetChannelReliability *rel; | ||
1217 | struct CadetReliableMessage *copy; | ||
1218 | uint32_t mid; | ||
1219 | uint16_t type; | ||
1220 | uint16_t size; | ||
1221 | |||
1222 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1223 | mid = rel->mid_send - 1; | ||
1224 | type = ntohs (msg->type); | ||
1225 | size = ntohs (msg->size); | ||
1226 | |||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u %s\n", mid, GM_m2s (type)); | ||
1228 | copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size); | ||
1229 | LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy); | ||
1230 | copy->mid = mid; | ||
1231 | copy->rel = rel; | ||
1232 | copy->type = type; | ||
1233 | memcpy (©[1], msg, size); | ||
1234 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy); | ||
1235 | ch->pending_messages++; | ||
1236 | |||
1237 | return copy; | ||
1238 | } | ||
1239 | |||
1240 | |||
1241 | /** | ||
1242 | * Create a new channel. | ||
1243 | * | ||
1244 | * @param t Tunnel this channel is in. | ||
1245 | * @param owner Client that owns the channel, NULL for foreign channels. | ||
1246 | * @param lid_root Local ID for root client. | ||
1247 | * | ||
1248 | * @return A new initialized channel. NULL on error. | ||
1249 | */ | ||
1250 | static struct CadetChannel * | ||
1251 | channel_new (struct CadetTunnel3 *t, | ||
1252 | struct CadetClient *owner, | ||
1253 | CADET_ChannelNumber lid_root) | ||
1254 | { | ||
1255 | struct CadetChannel *ch; | ||
1256 | |||
1257 | ch = GNUNET_new (struct CadetChannel); | ||
1258 | ch->root = owner; | ||
1259 | ch->lid_root = lid_root; | ||
1260 | ch->t = t; | ||
1261 | |||
1262 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
1263 | |||
1264 | if (NULL != owner) | ||
1265 | { | ||
1266 | ch->gid = GMT_get_next_chid (t); | ||
1267 | GML_channel_add (owner, lid_root, ch); | ||
1268 | } | ||
1269 | GMT_add_channel (t, ch); | ||
1270 | |||
1271 | return ch; | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | /** | ||
1276 | * Handle a loopback message: call the appropriate handler for the message type. | ||
1277 | * | ||
1278 | * @param ch Channel this message is on. | ||
1279 | * @param msgh Message header. | ||
1280 | * @param fwd Is this FWD traffic? | ||
1281 | */ | ||
1282 | void | ||
1283 | handle_loopback (struct CadetChannel *ch, | ||
1284 | const struct GNUNET_MessageHeader *msgh, | ||
1285 | int fwd) | ||
1286 | { | ||
1287 | uint16_t type; | ||
1288 | |||
1289 | type = ntohs (msgh->type); | ||
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "Loopback %s %s message!\n", | ||
1292 | GM_f2s (fwd), GM_m2s (type)); | ||
1293 | |||
1294 | switch (type) | ||
1295 | { | ||
1296 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
1297 | /* Don't send hop ACK, wait for client to ACK */ | ||
1298 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SEND loopback %u (%u)\n", | ||
1299 | ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs (msgh->size)); | ||
1300 | GMCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd); | ||
1301 | break; | ||
1302 | |||
1303 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
1304 | GMCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd); | ||
1305 | break; | ||
1306 | |||
1307 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
1308 | GMCH_handle_create (ch->t, | ||
1309 | (struct GNUNET_CADET_ChannelCreate *) msgh); | ||
1310 | break; | ||
1311 | |||
1312 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
1313 | GMCH_handle_ack (ch, | ||
1314 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1315 | fwd); | ||
1316 | break; | ||
1317 | |||
1318 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
1319 | GMCH_handle_nack (ch); | ||
1320 | break; | ||
1321 | |||
1322 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1323 | GMCH_handle_destroy (ch, | ||
1324 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1325 | fwd); | ||
1326 | break; | ||
1327 | |||
1328 | default: | ||
1329 | GNUNET_break_op (0); | ||
1330 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1331 | "end-to-end message not known (%u)\n", | ||
1332 | ntohs (msgh->type)); | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | |||
1337 | |||
1338 | /******************************************************************************/ | ||
1339 | /******************************** API ***********************************/ | ||
1340 | /******************************************************************************/ | ||
1341 | |||
1342 | /** | ||
1343 | * Destroy a channel and free all resources. | ||
1344 | * | ||
1345 | * @param ch Channel to destroy. | ||
1346 | */ | ||
1347 | void | ||
1348 | GMCH_destroy (struct CadetChannel *ch) | ||
1349 | { | ||
1350 | struct CadetClient *c; | ||
1351 | struct CadetTunnel3 *t; | ||
1352 | |||
1353 | if (NULL == ch) | ||
1354 | return; | ||
1355 | if (2 == ch->destroy) | ||
1356 | return; /* recursive call */ | ||
1357 | ch->destroy = 2; | ||
1358 | |||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n", | ||
1360 | GMT_2s (ch->t), ch->gid); | ||
1361 | GMCH_debug (ch); | ||
1362 | |||
1363 | c = ch->root; | ||
1364 | if (NULL != c) | ||
1365 | { | ||
1366 | GML_channel_remove (c, ch->lid_root, ch); | ||
1367 | } | ||
1368 | |||
1369 | c = ch->dest; | ||
1370 | if (NULL != c) | ||
1371 | { | ||
1372 | GML_channel_remove (c, ch->lid_dest, ch); | ||
1373 | } | ||
1374 | |||
1375 | channel_rel_free_all (ch->root_rel); | ||
1376 | channel_rel_free_all (ch->dest_rel); | ||
1377 | |||
1378 | t = ch->t; | ||
1379 | GMT_remove_channel (t, ch); | ||
1380 | GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO); | ||
1381 | |||
1382 | GNUNET_free (ch); | ||
1383 | GMT_destroy_if_empty (t); | ||
1384 | } | ||
1385 | |||
1386 | |||
1387 | /** | ||
1388 | * Get the channel's public ID. | ||
1389 | * | ||
1390 | * @param ch Channel. | ||
1391 | * | ||
1392 | * @return ID used to identify the channel with the remote peer. | ||
1393 | */ | ||
1394 | CADET_ChannelNumber | ||
1395 | GMCH_get_id (const struct CadetChannel *ch) | ||
1396 | { | ||
1397 | return ch->gid; | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * Get the channel tunnel. | ||
1403 | * | ||
1404 | * @param ch Channel to get the tunnel from. | ||
1405 | * | ||
1406 | * @return tunnel of the channel. | ||
1407 | */ | ||
1408 | struct CadetTunnel3 * | ||
1409 | GMCH_get_tunnel (const struct CadetChannel *ch) | ||
1410 | { | ||
1411 | return ch->t; | ||
1412 | } | ||
1413 | |||
1414 | |||
1415 | /** | ||
1416 | * Get free buffer space towards the client on a specific channel. | ||
1417 | * | ||
1418 | * @param ch Channel. | ||
1419 | * @param fwd Is query about FWD traffic? | ||
1420 | * | ||
1421 | * @return Free buffer space [0 - 64] | ||
1422 | */ | ||
1423 | unsigned int | ||
1424 | GMCH_get_buffer (struct CadetChannel *ch, int fwd) | ||
1425 | { | ||
1426 | struct CadetChannelReliability *rel; | ||
1427 | |||
1428 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1429 | |||
1430 | /* If rel is NULL it means that the end is not yet created, | ||
1431 | * most probably is a loopback channel at the point of sending | ||
1432 | * the ChannelCreate to itself. | ||
1433 | */ | ||
1434 | if (NULL == rel) | ||
1435 | return 64; | ||
1436 | |||
1437 | return (64 - rel->n_recv); | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | /** | ||
1442 | * Get flow control status of end point: is client allow to send? | ||
1443 | * | ||
1444 | * @param ch Channel. | ||
1445 | * @param fwd Is query about FWD traffic? (Request root status). | ||
1446 | * | ||
1447 | * @return #GNUNET_YES if client is allowed to send us data. | ||
1448 | */ | ||
1449 | int | ||
1450 | GMCH_get_allowed (struct CadetChannel *ch, int fwd) | ||
1451 | { | ||
1452 | struct CadetChannelReliability *rel; | ||
1453 | |||
1454 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1455 | |||
1456 | if (NULL == rel) | ||
1457 | { | ||
1458 | /* Probably shutting down: root/dest NULL'ed to mark disconnection */ | ||
1459 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | return rel->client_allowed; | ||
1464 | } | ||
1465 | |||
1466 | |||
1467 | /** | ||
1468 | * Is the root client for this channel on this peer? | ||
1469 | * | ||
1470 | * @param ch Channel. | ||
1471 | * @param fwd Is this for fwd traffic? | ||
1472 | * | ||
1473 | * @return #GNUNET_YES in case it is. | ||
1474 | */ | ||
1475 | int | ||
1476 | GMCH_is_origin (struct CadetChannel *ch, int fwd) | ||
1477 | { | ||
1478 | struct CadetClient *c; | ||
1479 | |||
1480 | c = fwd ? ch->root : ch->dest; | ||
1481 | return NULL != c; | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /** | ||
1486 | * Is the destination client for this channel on this peer? | ||
1487 | * | ||
1488 | * @param ch Channel. | ||
1489 | * @param fwd Is this for fwd traffic? | ||
1490 | * | ||
1491 | * @return #GNUNET_YES in case it is. | ||
1492 | */ | ||
1493 | int | ||
1494 | GMCH_is_terminal (struct CadetChannel *ch, int fwd) | ||
1495 | { | ||
1496 | struct CadetClient *c; | ||
1497 | |||
1498 | c = fwd ? ch->dest : ch->root; | ||
1499 | return NULL != c; | ||
1500 | } | ||
1501 | |||
1502 | |||
1503 | /** | ||
1504 | * Send an end-to-end ACK message for the most recent in-sequence payload. | ||
1505 | * | ||
1506 | * If channel is not reliable, do nothing. | ||
1507 | * | ||
1508 | * @param ch Channel this is about. | ||
1509 | * @param fwd Is for FWD traffic? (ACK dest->owner) | ||
1510 | */ | ||
1511 | void | ||
1512 | GMCH_send_data_ack (struct CadetChannel *ch, int fwd) | ||
1513 | { | ||
1514 | struct GNUNET_CADET_DataACK msg; | ||
1515 | struct CadetChannelReliability *rel; | ||
1516 | struct CadetReliableMessage *copy; | ||
1517 | unsigned int delta; | ||
1518 | uint64_t mask; | ||
1519 | uint32_t ack; | ||
1520 | |||
1521 | if (GNUNET_NO == ch->reliable) | ||
1522 | { | ||
1523 | return; | ||
1524 | } | ||
1525 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1526 | ack = rel->mid_recv - 1; | ||
1527 | LOG (GNUNET_ERROR_TYPE_INFO, "===> DATA_ACK for %u\n", ack); | ||
1528 | |||
1529 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK); | ||
1530 | msg.header.size = htons (sizeof (msg)); | ||
1531 | msg.chid = htonl (ch->gid); | ||
1532 | msg.futures = 0; | ||
1533 | for (copy = rel->head_recv; NULL != copy; copy = copy->next) | ||
1534 | { | ||
1535 | if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA) | ||
1536 | { | ||
1537 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1538 | "!! Type %s, expected DATA\n", | ||
1539 | GM_m2s (copy->type)); | ||
1540 | continue; | ||
1541 | } | ||
1542 | if (copy->mid == ack + 1) | ||
1543 | { | ||
1544 | ack++; | ||
1545 | continue; | ||
1546 | } | ||
1547 | delta = copy->mid - (ack + 1); | ||
1548 | if (63 < delta) | ||
1549 | break; | ||
1550 | mask = 0x1LL << delta; | ||
1551 | msg.futures |= mask; | ||
1552 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1553 | " !! setting bit for %u (delta %u) (%llX) -> %llX\n", | ||
1554 | copy->mid, delta, mask, msg.futures); | ||
1555 | } | ||
1556 | msg.mid = htonl (ack); | ||
1557 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1558 | "!!! ACK for %u, futures %llX\n", | ||
1559 | ack, msg.futures); | ||
1560 | |||
1561 | GMCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); | ||
1562 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n"); | ||
1563 | } | ||
1564 | |||
1565 | |||
1566 | /** | ||
1567 | * Allow a client to send us more data, in case it was choked. | ||
1568 | * | ||
1569 | * @param ch Channel. | ||
1570 | * @param fwd Is this about FWD traffic? (Root client). | ||
1571 | */ | ||
1572 | void | ||
1573 | GMCH_allow_client (struct CadetChannel *ch, int fwd) | ||
1574 | { | ||
1575 | struct CadetChannelReliability *rel; | ||
1576 | unsigned int buffer; | ||
1577 | |||
1578 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n"); | ||
1579 | |||
1580 | if (CADET_CHANNEL_READY != ch->state) | ||
1581 | { | ||
1582 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n"); | ||
1583 | return; | ||
1584 | } | ||
1585 | |||
1586 | if (GNUNET_YES == ch->reliable) | ||
1587 | { | ||
1588 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1589 | if (NULL == rel) | ||
1590 | { | ||
1591 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1592 | return; | ||
1593 | } | ||
1594 | if (NULL != rel->head_sent) | ||
1595 | { | ||
1596 | if (64 <= rel->mid_send - rel->head_sent->mid) | ||
1597 | { | ||
1598 | LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n"); | ||
1599 | return; | ||
1600 | } | ||
1601 | else | ||
1602 | LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n", | ||
1603 | rel->head_sent->mid, rel->mid_send); | ||
1604 | } | ||
1605 | else | ||
1606 | { | ||
1607 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n"); | ||
1608 | } | ||
1609 | } | ||
1610 | |||
1611 | if (is_loopback (ch)) | ||
1612 | buffer = GMCH_get_buffer (ch, fwd); | ||
1613 | else | ||
1614 | buffer = GMT_get_connections_buffer (ch->t); | ||
1615 | |||
1616 | if (0 == buffer) | ||
1617 | { | ||
1618 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n"); | ||
1619 | return; | ||
1620 | } | ||
1621 | |||
1622 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer); | ||
1623 | send_client_ack (ch, fwd); | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | /** | ||
1628 | * Log channel info. | ||
1629 | * | ||
1630 | * @param ch Channel. | ||
1631 | */ | ||
1632 | void | ||
1633 | GMCH_debug (struct CadetChannel *ch) | ||
1634 | { | ||
1635 | if (NULL == ch) | ||
1636 | { | ||
1637 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n"); | ||
1638 | return; | ||
1639 | } | ||
1640 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n", | ||
1641 | GMT_2s (ch->t), ch->gid, ch); | ||
1642 | LOG (GNUNET_ERROR_TYPE_DEBUG, " root %p/%p\n", | ||
1643 | ch->root, ch->root_rel); | ||
1644 | if (NULL != ch->root) | ||
1645 | { | ||
1646 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->root)); | ||
1647 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", | ||
1648 | ch->root_rel->client_ready ? "YES" : "NO"); | ||
1649 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_root); | ||
1650 | } | ||
1651 | LOG (GNUNET_ERROR_TYPE_DEBUG, " dest %p/%p\n", | ||
1652 | ch->dest, ch->dest_rel); | ||
1653 | if (NULL != ch->dest) | ||
1654 | { | ||
1655 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->dest)); | ||
1656 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", | ||
1657 | ch->dest_rel->client_ready ? "YES" : "NO"); | ||
1658 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_dest); | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | |||
1663 | /** | ||
1664 | * Handle an ACK given by a client. | ||
1665 | * | ||
1666 | * Mark client as ready and send him any buffered data we could have for him. | ||
1667 | * | ||
1668 | * @param ch Channel. | ||
1669 | * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK) | ||
1670 | */ | ||
1671 | void | ||
1672 | GMCH_handle_local_ack (struct CadetChannel *ch, int fwd) | ||
1673 | { | ||
1674 | struct CadetChannelReliability *rel; | ||
1675 | struct CadetClient *c; | ||
1676 | |||
1677 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1678 | c = fwd ? ch->dest : ch->root; | ||
1679 | |||
1680 | rel->client_ready = GNUNET_YES; | ||
1681 | send_client_buffered_data (ch, c, fwd); | ||
1682 | |||
1683 | if (GNUNET_YES == ch->destroy && 0 == rel->n_recv) | ||
1684 | { | ||
1685 | send_destroy (ch, GNUNET_YES); | ||
1686 | GMCH_destroy (ch); | ||
1687 | } | ||
1688 | /* if loopback is marked for destruction, no need to ACK to the other peer, | ||
1689 | * it requested the destruction and is already gone, therefore, else if. | ||
1690 | */ | ||
1691 | else if (is_loopback (ch)) | ||
1692 | { | ||
1693 | unsigned int buffer; | ||
1694 | |||
1695 | buffer = GMCH_get_buffer (ch, fwd); | ||
1696 | if (0 < buffer) | ||
1697 | GMCH_allow_client (ch, fwd); | ||
1698 | |||
1699 | return; | ||
1700 | } | ||
1701 | GMT_send_connection_acks (ch->t); | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | /** | ||
1706 | * Handle data given by a client. | ||
1707 | * | ||
1708 | * Check whether the client is allowed to send in this tunnel, save if channel | ||
1709 | * is reliable and send an ACK to the client if there is still buffer space | ||
1710 | * in the tunnel. | ||
1711 | * | ||
1712 | * @param ch Channel. | ||
1713 | * @param c Client which sent the data. | ||
1714 | * @param message Message. | ||
1715 | * @param fwd Is this a FWD data? | ||
1716 | * | ||
1717 | * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. | ||
1718 | */ | ||
1719 | int | ||
1720 | GMCH_handle_local_data (struct CadetChannel *ch, | ||
1721 | struct CadetClient *c, | ||
1722 | struct GNUNET_MessageHeader *message, | ||
1723 | int fwd) | ||
1724 | { | ||
1725 | struct CadetChannelReliability *rel; | ||
1726 | struct GNUNET_CADET_Data *payload; | ||
1727 | size_t size = ntohs (message->size); | ||
1728 | uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size; | ||
1729 | unsigned char cbuf[p2p_size]; | ||
1730 | |||
1731 | /* Is the client in the channel? */ | ||
1732 | if ( !( (fwd && | ||
1733 | ch->root == c) | ||
1734 | || | ||
1735 | (!fwd && | ||
1736 | ch->dest == c) ) ) | ||
1737 | { | ||
1738 | GNUNET_break_op (0); | ||
1739 | return GNUNET_SYSERR; | ||
1740 | } | ||
1741 | |||
1742 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1743 | |||
1744 | if (GNUNET_NO == rel->client_allowed) | ||
1745 | { | ||
1746 | GNUNET_break_op (0); | ||
1747 | return GNUNET_SYSERR; | ||
1748 | } | ||
1749 | |||
1750 | rel->client_allowed = GNUNET_NO; | ||
1751 | |||
1752 | /* Ok, everything is correct, send the message. */ | ||
1753 | payload = (struct GNUNET_CADET_Data *) cbuf; | ||
1754 | payload->mid = htonl (rel->mid_send); | ||
1755 | rel->mid_send++; | ||
1756 | memcpy (&payload[1], message, size); | ||
1757 | payload->header.size = htons (p2p_size); | ||
1758 | payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA); | ||
1759 | payload->chid = htonl (ch->gid); | ||
1760 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); | ||
1761 | GMCH_send_prebuilt_message (&payload->header, ch, fwd, NULL); | ||
1762 | |||
1763 | if (is_loopback (ch)) | ||
1764 | { | ||
1765 | if (GMCH_get_buffer (ch, fwd) > 0) | ||
1766 | GMCH_allow_client (ch, fwd); | ||
1767 | |||
1768 | return GNUNET_OK; | ||
1769 | } | ||
1770 | |||
1771 | if (GMT_get_connections_buffer (ch->t) > 0) | ||
1772 | { | ||
1773 | GMCH_allow_client (ch, fwd); | ||
1774 | } | ||
1775 | |||
1776 | return GNUNET_OK; | ||
1777 | } | ||
1778 | |||
1779 | |||
1780 | /** | ||
1781 | * Handle a channel destroy requested by a client. | ||
1782 | * | ||
1783 | * Destroy the channel and the tunnel in case this was the last channel. | ||
1784 | * | ||
1785 | * @param ch Channel. | ||
1786 | * @param c Client that requested the destruction (to avoid notifying him). | ||
1787 | * @param is_root Is the request coming from root? | ||
1788 | */ | ||
1789 | void | ||
1790 | GMCH_handle_local_destroy (struct CadetChannel *ch, | ||
1791 | struct CadetClient *c, | ||
1792 | int is_root) | ||
1793 | { | ||
1794 | ch->destroy = GNUNET_YES; | ||
1795 | /* Cleanup after the tunnel */ | ||
1796 | if (GNUNET_NO == is_root && c == ch->dest) | ||
1797 | { | ||
1798 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c)); | ||
1799 | GML_client_delete_channel (c, ch, ch->lid_dest); | ||
1800 | ch->dest = NULL; | ||
1801 | } | ||
1802 | if (GNUNET_YES == is_root && c == ch->root) | ||
1803 | { | ||
1804 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c)); | ||
1805 | GML_client_delete_channel (c, ch, ch->lid_root); | ||
1806 | ch->root = NULL; | ||
1807 | } | ||
1808 | |||
1809 | send_destroy (ch, GNUNET_NO); | ||
1810 | if (0 == ch->pending_messages) | ||
1811 | GMCH_destroy (ch); | ||
1812 | } | ||
1813 | |||
1814 | |||
1815 | /** | ||
1816 | * Handle a channel create requested by a client. | ||
1817 | * | ||
1818 | * Create the channel and the tunnel in case this was the first0 channel. | ||
1819 | * | ||
1820 | * @param c Client that requested the creation (will be the root). | ||
1821 | * @param msg Create Channel message. | ||
1822 | * | ||
1823 | * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise. | ||
1824 | */ | ||
1825 | int | ||
1826 | GMCH_handle_local_create (struct CadetClient *c, | ||
1827 | struct GNUNET_CADET_ChannelMessage *msg) | ||
1828 | { | ||
1829 | struct CadetChannel *ch; | ||
1830 | struct CadetTunnel3 *t; | ||
1831 | struct CadetPeer *peer; | ||
1832 | CADET_ChannelNumber chid; | ||
1833 | |||
1834 | LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", | ||
1835 | GNUNET_i2s (&msg->peer), ntohl (msg->port)); | ||
1836 | chid = ntohl (msg->channel_id); | ||
1837 | |||
1838 | /* Sanity check for duplicate channel IDs */ | ||
1839 | if (NULL != GML_channel_get (c, chid)) | ||
1840 | { | ||
1841 | GNUNET_break (0); | ||
1842 | return GNUNET_SYSERR; | ||
1843 | } | ||
1844 | |||
1845 | peer = GMP_get (&msg->peer); | ||
1846 | GMP_add_tunnel (peer); | ||
1847 | t = GMP_get_tunnel (peer); | ||
1848 | |||
1849 | if (GMP_get_short_id (peer) == myid) | ||
1850 | { | ||
1851 | GMT_change_cstate (t, CADET_TUNNEL3_READY); | ||
1852 | } | ||
1853 | else | ||
1854 | { | ||
1855 | /* FIXME change to a tunnel API, eliminate ch <-> peer connection */ | ||
1856 | GMP_connect (peer); | ||
1857 | } | ||
1858 | |||
1859 | /* Create channel */ | ||
1860 | ch = channel_new (t, c, chid); | ||
1861 | if (NULL == ch) | ||
1862 | { | ||
1863 | GNUNET_break (0); | ||
1864 | return GNUNET_SYSERR; | ||
1865 | } | ||
1866 | ch->port = ntohl (msg->port); | ||
1867 | channel_set_options (ch, ntohl (msg->opt)); | ||
1868 | |||
1869 | /* In unreliable channels, we'll use the DLL to buffer BCK data */ | ||
1870 | ch->root_rel = GNUNET_new (struct CadetChannelReliability); | ||
1871 | ch->root_rel->ch = ch; | ||
1872 | ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
1873 | ch->root_rel->expected_delay.rel_value_us = 0; | ||
1874 | |||
1875 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GMCH_2s (ch)); | ||
1876 | |||
1877 | send_create (ch); | ||
1878 | |||
1879 | return GNUNET_OK; | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | /** | ||
1884 | * Handler for cadet network payload traffic. | ||
1885 | * | ||
1886 | * @param ch Channel for the message. | ||
1887 | * @param msg Unencryted data message. | ||
1888 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1889 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1890 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1891 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1892 | */ | ||
1893 | void | ||
1894 | GMCH_handle_data (struct CadetChannel *ch, | ||
1895 | const struct GNUNET_CADET_Data *msg, | ||
1896 | int fwd) | ||
1897 | { | ||
1898 | struct CadetChannelReliability *rel; | ||
1899 | struct CadetClient *c; | ||
1900 | uint32_t mid; | ||
1901 | |||
1902 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
1903 | if (GNUNET_SYSERR == fwd) | ||
1904 | { | ||
1905 | if (is_loopback (ch)) | ||
1906 | { | ||
1907 | /* It is a loopback channel after all... */ | ||
1908 | GNUNET_break (0); | ||
1909 | return; | ||
1910 | } | ||
1911 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
1912 | } | ||
1913 | |||
1914 | /* Initialize FWD/BCK data */ | ||
1915 | c = fwd ? ch->dest : ch->root; | ||
1916 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1917 | |||
1918 | if (NULL == c) | ||
1919 | { | ||
1920 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | if (CADET_CHANNEL_READY != ch->state) | ||
1925 | { | ||
1926 | if (GNUNET_NO == fwd) | ||
1927 | { | ||
1928 | /* If we are the root, this means the other peer has sent traffic before | ||
1929 | * receiving our ACK. Even if the SYNACK goes missing, no traffic should | ||
1930 | * be sent before the ACK. | ||
1931 | */ | ||
1932 | GNUNET_break_op (0); | ||
1933 | return; | ||
1934 | } | ||
1935 | /* If we are the dest, this means that the SYNACK got to the root but | ||
1936 | * the ACK went missing. Treat this as an ACK. | ||
1937 | */ | ||
1938 | channel_confirm (ch, GNUNET_NO); | ||
1939 | } | ||
1940 | |||
1941 | GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO); | ||
1942 | |||
1943 | mid = ntohl (msg->mid); | ||
1944 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== DATA %u %s on channel %s\n", | ||
1945 | mid, GM_f2s (fwd), GMCH_2s (ch)); | ||
1946 | |||
1947 | if (GNUNET_NO == ch->reliable || | ||
1948 | ( !GM_is_pid_bigger (rel->mid_recv, mid) && | ||
1949 | GM_is_pid_bigger (rel->mid_recv + 64, mid) ) ) | ||
1950 | { | ||
1951 | LOG (GNUNET_ERROR_TYPE_DEBUG, "RECV %u (%u)\n", | ||
1952 | mid, ntohs (msg->header.size)); | ||
1953 | if (GNUNET_YES == ch->reliable) | ||
1954 | { | ||
1955 | /* Is this the exact next expected messasge? */ | ||
1956 | if (mid == rel->mid_recv) | ||
1957 | { | ||
1958 | LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n"); | ||
1959 | rel->mid_recv++; | ||
1960 | send_client_data (ch, msg, fwd); | ||
1961 | } | ||
1962 | else | ||
1963 | { | ||
1964 | LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n"); | ||
1965 | add_buffered_data (msg, rel); | ||
1966 | } | ||
1967 | } | ||
1968 | else | ||
1969 | { | ||
1970 | /* Tunnel is unreliable: send to clients directly */ | ||
1971 | /* FIXME: accept Out Of Order traffic */ | ||
1972 | rel->mid_recv = mid + 1; | ||
1973 | send_client_data (ch, msg, fwd); | ||
1974 | } | ||
1975 | } | ||
1976 | else | ||
1977 | { | ||
1978 | GNUNET_break_op (GM_is_pid_bigger (rel->mid_recv, mid)); | ||
1979 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1980 | "MID %u not expected (%u - %u), dropping!\n", | ||
1981 | mid, rel->mid_recv, rel->mid_recv + 63); | ||
1982 | } | ||
1983 | |||
1984 | GMCH_send_data_ack (ch, fwd); | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | /** | ||
1989 | * Handler for cadet network traffic end-to-end ACKs. | ||
1990 | * | ||
1991 | * @param ch Channel on which we got this message. | ||
1992 | * @param msg Data message. | ||
1993 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1994 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1995 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1996 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1997 | */ | ||
1998 | void | ||
1999 | GMCH_handle_data_ack (struct CadetChannel *ch, | ||
2000 | const struct GNUNET_CADET_DataACK *msg, | ||
2001 | int fwd) | ||
2002 | { | ||
2003 | struct CadetChannelReliability *rel; | ||
2004 | struct CadetReliableMessage *copy; | ||
2005 | struct CadetReliableMessage *next; | ||
2006 | uint32_t ack; | ||
2007 | int work; | ||
2008 | |||
2009 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2010 | if (GNUNET_SYSERR == fwd) | ||
2011 | { | ||
2012 | if (is_loopback (ch)) | ||
2013 | { | ||
2014 | /* It is a loopback channel after all... */ | ||
2015 | GNUNET_break (0); | ||
2016 | return; | ||
2017 | } | ||
2018 | /* Inverted: if message came 'FWD' is a 'BCK ACK'. */ | ||
2019 | fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES; | ||
2020 | } | ||
2021 | |||
2022 | ack = ntohl (msg->mid); | ||
2023 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s ACK %u\n", GM_f2s (fwd), ack); | ||
2024 | |||
2025 | if (GNUNET_YES == fwd) | ||
2026 | { | ||
2027 | rel = ch->root_rel; | ||
2028 | } | ||
2029 | else | ||
2030 | { | ||
2031 | rel = ch->dest_rel; | ||
2032 | } | ||
2033 | if (NULL == rel) | ||
2034 | { | ||
2035 | GNUNET_break_op (GNUNET_NO != ch->destroy); | ||
2036 | return; | ||
2037 | } | ||
2038 | |||
2039 | /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */ | ||
2040 | for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) | ||
2041 | { | ||
2042 | if (GM_is_pid_bigger (copy->mid, ack)) | ||
2043 | { | ||
2044 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid); | ||
2045 | channel_rel_free_sent (rel, msg); | ||
2046 | break; | ||
2047 | } | ||
2048 | work = GNUNET_YES; | ||
2049 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid); | ||
2050 | next = copy->next; | ||
2051 | if (GNUNET_YES == rel_message_free (copy, GNUNET_YES)) | ||
2052 | return; | ||
2053 | } | ||
2054 | |||
2055 | /* ACK client if needed and possible */ | ||
2056 | GMCH_allow_client (ch, fwd); | ||
2057 | |||
2058 | /* If some message was free'd, update the retransmission delay */ | ||
2059 | if (GNUNET_YES == work) | ||
2060 | { | ||
2061 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
2062 | { | ||
2063 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
2064 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
2065 | if (NULL != rel->head_sent && NULL == rel->head_sent->chq) | ||
2066 | { | ||
2067 | struct GNUNET_TIME_Absolute new_target; | ||
2068 | struct GNUNET_TIME_Relative delay; | ||
2069 | |||
2070 | delay = GNUNET_TIME_relative_multiply (rel->retry_timer, | ||
2071 | CADET_RETRANSMIT_MARGIN); | ||
2072 | new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp, | ||
2073 | delay); | ||
2074 | delay = GNUNET_TIME_absolute_get_remaining (new_target); | ||
2075 | rel->retry_task = | ||
2076 | GNUNET_SCHEDULER_add_delayed (delay, | ||
2077 | &channel_retransmit_message, | ||
2078 | rel); | ||
2079 | } | ||
2080 | } | ||
2081 | else | ||
2082 | { | ||
2083 | /* Work was done but no task was pending? Shouldn't happen! */ | ||
2084 | GNUNET_break (0); | ||
2085 | } | ||
2086 | } | ||
2087 | } | ||
2088 | |||
2089 | |||
2090 | /** | ||
2091 | * Handler for channel create messages. | ||
2092 | * | ||
2093 | * Does not have fwd parameter because it's always 'FWD': channel is incoming. | ||
2094 | * | ||
2095 | * @param t Tunnel this channel will be in. | ||
2096 | * @param msg Channel crate message. | ||
2097 | */ | ||
2098 | struct CadetChannel * | ||
2099 | GMCH_handle_create (struct CadetTunnel3 *t, | ||
2100 | const struct GNUNET_CADET_ChannelCreate *msg) | ||
2101 | { | ||
2102 | CADET_ChannelNumber chid; | ||
2103 | struct CadetChannel *ch; | ||
2104 | struct CadetClient *c; | ||
2105 | int new_channel; | ||
2106 | int reaction; | ||
2107 | |||
2108 | reaction = GNUNET_NO; | ||
2109 | chid = ntohl (msg->chid); | ||
2110 | ch = GMT_get_channel (t, chid); | ||
2111 | if (NULL == ch) | ||
2112 | { | ||
2113 | /* Create channel */ | ||
2114 | ch = channel_new (t, NULL, 0); | ||
2115 | ch->gid = chid; | ||
2116 | channel_set_options (ch, ntohl (msg->opt)); | ||
2117 | new_channel = GNUNET_YES; | ||
2118 | } | ||
2119 | else | ||
2120 | { | ||
2121 | new_channel = GNUNET_NO; | ||
2122 | } | ||
2123 | |||
2124 | if (GNUNET_YES == new_channel || GMT_is_loopback (t)) | ||
2125 | { | ||
2126 | /* Find a destination client */ | ||
2127 | ch->port = ntohl (msg->port); | ||
2128 | LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", ch->port); | ||
2129 | c = GML_client_get_by_port (ch->port); | ||
2130 | if (NULL == c) | ||
2131 | { | ||
2132 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n"); | ||
2133 | if (is_loopback (ch)) | ||
2134 | { | ||
2135 | LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n"); | ||
2136 | send_nack (ch); | ||
2137 | } | ||
2138 | else | ||
2139 | { | ||
2140 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n"); | ||
2141 | send_nack (ch); | ||
2142 | GMCH_destroy (ch); | ||
2143 | } | ||
2144 | return NULL; | ||
2145 | } | ||
2146 | else | ||
2147 | { | ||
2148 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c); | ||
2149 | } | ||
2150 | |||
2151 | add_destination (ch, c); | ||
2152 | if (GNUNET_YES == ch->reliable) | ||
2153 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); | ||
2154 | else | ||
2155 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n"); | ||
2156 | |||
2157 | send_client_create (ch); | ||
2158 | ch->state = CADET_CHANNEL_SENT; | ||
2159 | } | ||
2160 | else | ||
2161 | { | ||
2162 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n"); | ||
2163 | reaction = GNUNET_YES; | ||
2164 | if (GNUNET_SCHEDULER_NO_TASK != ch->dest_rel->retry_task) | ||
2165 | { | ||
2166 | LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n"); | ||
2167 | /* we were waiting to re-send our 'SYNACK', wait no more! */ | ||
2168 | GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task); | ||
2169 | ch->dest_rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
2170 | } | ||
2171 | } | ||
2172 | send_ack (ch, GNUNET_YES, reaction); | ||
2173 | |||
2174 | return ch; | ||
2175 | } | ||
2176 | |||
2177 | |||
2178 | /** | ||
2179 | * Handler for channel NACK messages. | ||
2180 | * | ||
2181 | * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. | ||
2182 | * | ||
2183 | * @param ch Channel. | ||
2184 | */ | ||
2185 | void | ||
2186 | GMCH_handle_nack (struct CadetChannel *ch) | ||
2187 | { | ||
2188 | send_client_nack (ch); | ||
2189 | GMCH_destroy (ch); | ||
2190 | } | ||
2191 | |||
2192 | |||
2193 | /** | ||
2194 | * Handler for channel ack messages. | ||
2195 | * | ||
2196 | * @param ch Channel. | ||
2197 | * @param msg Message. | ||
2198 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2199 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2200 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2201 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2202 | */ | ||
2203 | void | ||
2204 | GMCH_handle_ack (struct CadetChannel *ch, | ||
2205 | const struct GNUNET_CADET_ChannelManage *msg, | ||
2206 | int fwd) | ||
2207 | { | ||
2208 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2209 | if (GNUNET_SYSERR == fwd) | ||
2210 | { | ||
2211 | if (is_loopback (ch)) | ||
2212 | { | ||
2213 | /* It is a loopback channel after all... */ | ||
2214 | GNUNET_break (0); | ||
2215 | return; | ||
2216 | } | ||
2217 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2218 | } | ||
2219 | |||
2220 | channel_confirm (ch, !fwd); | ||
2221 | } | ||
2222 | |||
2223 | |||
2224 | /** | ||
2225 | * Handler for channel destroy messages. | ||
2226 | * | ||
2227 | * @param ch Channel to be destroyed of. | ||
2228 | * @param msg Message. | ||
2229 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2230 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2231 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2232 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2233 | */ | ||
2234 | void | ||
2235 | GMCH_handle_destroy (struct CadetChannel *ch, | ||
2236 | const struct GNUNET_CADET_ChannelManage *msg, | ||
2237 | int fwd) | ||
2238 | { | ||
2239 | struct CadetChannelReliability *rel; | ||
2240 | |||
2241 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2242 | if (GNUNET_SYSERR == fwd) | ||
2243 | { | ||
2244 | if (is_loopback (ch)) | ||
2245 | { | ||
2246 | /* It is a loopback channel after all... */ | ||
2247 | GNUNET_break (0); | ||
2248 | return; | ||
2249 | } | ||
2250 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2251 | } | ||
2252 | |||
2253 | GMCH_debug (ch); | ||
2254 | if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) ) | ||
2255 | { | ||
2256 | /* Not for us (don't destroy twice a half-open loopback channel) */ | ||
2257 | return; | ||
2258 | } | ||
2259 | |||
2260 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
2261 | if (0 == rel->n_recv) | ||
2262 | { | ||
2263 | send_destroy (ch, GNUNET_YES); | ||
2264 | GMCH_destroy (ch); | ||
2265 | } | ||
2266 | else | ||
2267 | { | ||
2268 | ch->destroy = GNUNET_YES; | ||
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | |||
2273 | /** | ||
2274 | * Sends an already built message on a channel. | ||
2275 | * | ||
2276 | * If the channel is on a loopback tunnel, notifies the appropriate destination | ||
2277 | * client locally. | ||
2278 | * | ||
2279 | * On a normal channel passes the message to the tunnel for encryption and | ||
2280 | * sending on a connection. | ||
2281 | * | ||
2282 | * This function DOES NOT save the message for retransmission. | ||
2283 | * | ||
2284 | * @param message Message to send. Function makes a copy of it. | ||
2285 | * @param ch Channel on which this message is transmitted. | ||
2286 | * @param fwd Is this a fwd message? | ||
2287 | * @param existing_copy This is a retransmission, don't save a copy. | ||
2288 | */ | ||
2289 | void | ||
2290 | GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2291 | struct CadetChannel *ch, int fwd, | ||
2292 | void *existing_copy) | ||
2293 | { | ||
2294 | struct CadetChannelQueue *chq; | ||
2295 | uint16_t type; | ||
2296 | |||
2297 | type = ntohs (message->type); | ||
2298 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %s on channel %s\n", | ||
2299 | GM_m2s (type), GM_f2s (fwd), GMCH_2s (ch)); | ||
2300 | |||
2301 | if (GMT_is_loopback (ch->t)) | ||
2302 | { | ||
2303 | handle_loopback (ch, message, fwd); | ||
2304 | return; | ||
2305 | } | ||
2306 | |||
2307 | switch (type) | ||
2308 | { | ||
2309 | struct GNUNET_CADET_Data *payload; | ||
2310 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
2311 | |||
2312 | payload = (struct GNUNET_CADET_Data *) message; | ||
2313 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %u\n", | ||
2314 | GM_m2s (type), ntohl (payload->mid)); | ||
2315 | if (GNUNET_YES == ch->reliable) | ||
2316 | { | ||
2317 | chq = GNUNET_new (struct CadetChannelQueue); | ||
2318 | chq->type = type; | ||
2319 | if (NULL == existing_copy) | ||
2320 | chq->copy = channel_save_copy (ch, message, fwd); | ||
2321 | else | ||
2322 | { | ||
2323 | chq->copy = (struct CadetReliableMessage *) existing_copy; | ||
2324 | if (NULL != chq->copy->chq) | ||
2325 | { | ||
2326 | /* Last retransmission was queued but not yet sent! | ||
2327 | * This retransmission was scheduled by a ch_message_sent which | ||
2328 | * followed a very fast RTT, so the tiny delay made the | ||
2329 | * retransmission function to execute before the previous | ||
2330 | * retransmitted message even had a chance to leave the peer. | ||
2331 | * Cancel this message and wait until the pending | ||
2332 | * retransmission leaves the peer and ch_message_sent starts | ||
2333 | * the timer for the next one. | ||
2334 | */ | ||
2335 | GNUNET_free (chq); | ||
2336 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2337 | " exisitng copy not yet transmitted!\n"); | ||
2338 | return; | ||
2339 | } | ||
2340 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2341 | " using existing copy: %p {r:%p q:%p t:%u}\n", | ||
2342 | existing_copy, | ||
2343 | chq->copy->rel, chq->copy->chq, chq->copy->type); | ||
2344 | } | ||
2345 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq); | ||
2346 | chq->copy->chq = chq; | ||
2347 | chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, | ||
2348 | NULL != existing_copy, | ||
2349 | &ch_message_sent, chq); | ||
2350 | /* q itself is stored in copy */ | ||
2351 | GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy); | ||
2352 | } | ||
2353 | else | ||
2354 | { | ||
2355 | fire_and_forget (message, ch, GNUNET_NO); | ||
2356 | } | ||
2357 | break; | ||
2358 | |||
2359 | |||
2360 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
2361 | if (GNUNET_YES == fwd || NULL != existing_copy) | ||
2362 | { | ||
2363 | /* BCK ACK (going FWD) is just a response for a SYNACK, don't keep*/ | ||
2364 | fire_and_forget (message, ch, GNUNET_YES); | ||
2365 | return; | ||
2366 | } | ||
2367 | /* fall-trough */ | ||
2368 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
2369 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
2370 | chq = GNUNET_new (struct CadetChannelQueue); | ||
2371 | chq->type = type; | ||
2372 | chq->rel = fwd ? ch->root_rel : ch->dest_rel; | ||
2373 | if (NULL != chq->rel->uniq) | ||
2374 | { | ||
2375 | if (NULL != chq->rel->uniq->tq) | ||
2376 | { | ||
2377 | GMT_cancel (chq->rel->uniq->tq); | ||
2378 | /* ch_message_sent is called, freeing and NULLing uniq */ | ||
2379 | } | ||
2380 | else | ||
2381 | { | ||
2382 | GNUNET_break (0); | ||
2383 | GNUNET_free (chq->rel->uniq); | ||
2384 | } | ||
2385 | } | ||
2386 | chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES, | ||
2387 | &ch_message_sent, chq); | ||
2388 | if (NULL == chq->tq) | ||
2389 | { | ||
2390 | GNUNET_break (0); | ||
2391 | GNUNET_free (chq); | ||
2392 | chq = NULL; | ||
2393 | return; | ||
2394 | } | ||
2395 | chq->rel->uniq = chq; | ||
2396 | break; | ||
2397 | |||
2398 | |||
2399 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
2400 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
2401 | fire_and_forget (message, ch, GNUNET_YES); | ||
2402 | break; | ||
2403 | |||
2404 | |||
2405 | default: | ||
2406 | GNUNET_break (0); | ||
2407 | LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s unknown!\n", GM_m2s (type)); | ||
2408 | fire_and_forget (message, ch, GNUNET_YES); | ||
2409 | } | ||
2410 | } | ||
2411 | |||
2412 | |||
2413 | /** | ||
2414 | * Get the static string for identification of the channel. | ||
2415 | * | ||
2416 | * @param ch Channel. | ||
2417 | * | ||
2418 | * @return Static string with the channel IDs. | ||
2419 | */ | ||
2420 | const char * | ||
2421 | GMCH_2s (const struct CadetChannel *ch) | ||
2422 | { | ||
2423 | static char buf[64]; | ||
2424 | |||
2425 | if (NULL == ch) | ||
2426 | return "(NULL Channel)"; | ||
2427 | |||
2428 | sprintf (buf, "%s:%u gid:%X (%X / %X)", | ||
2429 | GMT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest); | ||
2430 | |||
2431 | return buf; | ||
2432 | } | ||