diff options
author | David Brodski <david@brodski.eu> | 2010-11-09 22:24:58 +0000 |
---|---|---|
committer | David Brodski <david@brodski.eu> | 2010-11-09 22:24:58 +0000 |
commit | 3db08333ec2b301cc8f204ad74f5aa8a25e3426f (patch) | |
tree | eaee71e79c7f8bbc91e0c21842bd18af792b159d /src/transport/plugin_transport_wlan.c | |
parent | e0dd7bcc0b9417f5bbd2bf910ec8c6a967a66c77 (diff) | |
download | gnunet-3db08333ec2b301cc8f204ad74f5aa8a25e3426f.tar.gz gnunet-3db08333ec2b301cc8f204ad74f5aa8a25e3426f.zip |
wlan: seperate fragment and session queue
wlan: schedule for timeouts used
dll: insert at tail
dll: insert before element
Diffstat (limited to 'src/transport/plugin_transport_wlan.c')
-rw-r--r-- | src/transport/plugin_transport_wlan.c | 798 |
1 files changed, 427 insertions, 371 deletions
diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c index 5ebe0a76d..4b83db3e9 100644 --- a/src/transport/plugin_transport_wlan.c +++ b/src/transport/plugin_transport_wlan.c | |||
@@ -48,6 +48,7 @@ | |||
48 | 48 | ||
49 | #define FRAGMENT_TIMEOUT 1000 | 49 | #define FRAGMENT_TIMEOUT 1000 |
50 | 50 | ||
51 | #define FRAGMENT_QUEUE_SIZE 10 | ||
51 | 52 | ||
52 | #define DEBUG_wlan GNUNET_NO | 53 | #define DEBUG_wlan GNUNET_NO |
53 | 54 | ||
@@ -164,6 +165,24 @@ struct Plugin | |||
164 | */ | 165 | */ |
165 | uint pendingsessions; | 166 | uint pendingsessions; |
166 | 167 | ||
168 | /** | ||
169 | * Messages in the fragmentation queue, head | ||
170 | */ | ||
171 | |||
172 | struct FragmentMessage * pending_Fragment_Messages_head; | ||
173 | |||
174 | /** | ||
175 | * Messages in the fragmentation queue, tail | ||
176 | */ | ||
177 | |||
178 | struct FragmentMessage * pending_Fragment_Messages_tail; | ||
179 | |||
180 | /** | ||
181 | * number of pending fragment message | ||
182 | */ | ||
183 | |||
184 | uint pending_fragment_messages; | ||
185 | |||
167 | }; | 186 | }; |
168 | 187 | ||
169 | //TODO doxigen | 188 | //TODO doxigen |
@@ -177,14 +196,50 @@ struct Sessionqueue | |||
177 | 196 | ||
178 | //TODO doxigen | 197 | //TODO doxigen |
179 | 198 | ||
180 | struct FragmentQueue | 199 | struct AckQueue |
181 | { | 200 | { |
182 | struct FragmentQueue * next; | 201 | struct AckQueue * next; |
183 | struct FragmentQueue * prev; | 202 | struct AckQueue * prev; |
184 | int fragment_num; | 203 | int fragment_num; |
185 | }; | 204 | }; |
186 | 205 | ||
187 | /** | 206 | /** |
207 | * Information kept for each message that is yet to | ||
208 | * be transmitted. | ||
209 | */ | ||
210 | struct PendingMessage | ||
211 | { | ||
212 | |||
213 | /** | ||
214 | * The pending message | ||
215 | */ | ||
216 | char *msg; | ||
217 | |||
218 | /** | ||
219 | * Continuation function to call once the message | ||
220 | * has been sent. Can be NULL if there is no | ||
221 | * continuation to call. | ||
222 | */ | ||
223 | GNUNET_TRANSPORT_TransmitContinuation transmit_cont; | ||
224 | |||
225 | /** | ||
226 | * Cls for transmit_cont | ||
227 | */ | ||
228 | void * transmit_cont_cls; | ||
229 | |||
230 | /** | ||
231 | * Timeout value for the pending message. | ||
232 | */ | ||
233 | struct GNUNET_TIME_Absolute timeout; | ||
234 | |||
235 | /** | ||
236 | * Size of the message | ||
237 | */ | ||
238 | size_t message_size; | ||
239 | |||
240 | }; | ||
241 | |||
242 | /** | ||
188 | * Session handle for connections. | 243 | * Session handle for connections. |
189 | */ | 244 | */ |
190 | struct Session | 245 | struct Session |
@@ -201,16 +256,10 @@ struct Session | |||
201 | struct Plugin *plugin; | 256 | struct Plugin *plugin; |
202 | 257 | ||
203 | /** | 258 | /** |
204 | * Messages currently pending for transmission | 259 | * Message currently pending for transmission |
205 | * to this peer, if any. | 260 | * to this peer, if any. |
206 | */ | 261 | */ |
207 | struct PendingMessage *pending_messages_head; | 262 | struct PendingMessage *pending_message; |
208 | |||
209 | /** | ||
210 | * Messages currently pending for transmission | ||
211 | * to this peer, if any. | ||
212 | */ | ||
213 | struct PendingMessage *pending_messages_tail; | ||
214 | 263 | ||
215 | /** | 264 | /** |
216 | * To whom are we talking to (set to our identity | 265 | * To whom are we talking to (set to our identity |
@@ -241,7 +290,7 @@ struct Session | |||
241 | struct GNUNET_TIME_Absolute last_activity; | 290 | struct GNUNET_TIME_Absolute last_activity; |
242 | 291 | ||
243 | /** | 292 | /** |
244 | * current number for message incoming , to distinguish between the messages | 293 | * current number for message incoming, to distinguish between the messages |
245 | */ | 294 | */ |
246 | uint32_t message_id_in; | 295 | uint32_t message_id_in; |
247 | 296 | ||
@@ -250,79 +299,76 @@ struct Session | |||
250 | */ | 299 | */ |
251 | uint32_t message_id_out; | 300 | uint32_t message_id_out; |
252 | 301 | ||
302 | /** | ||
303 | * does this session have a message in the fragment queue | ||
304 | */ | ||
305 | |||
306 | int has_fragment; | ||
253 | 307 | ||
254 | }; | 308 | }; |
255 | 309 | ||
256 | /** | 310 | |
257 | * Information kept for each message that is yet to | 311 | |
258 | * be transmitted. | 312 | |
259 | */ | 313 | struct FragmentMessage |
260 | struct PendingMessage | ||
261 | { | 314 | { |
315 | /** | ||
316 | * Session this message belongs to | ||
317 | */ | ||
262 | 318 | ||
263 | /** | 319 | struct Session *session; |
264 | * This is a doubly-linked list. | ||
265 | */ | ||
266 | struct PendingMessage *next; | ||
267 | 320 | ||
268 | /** | 321 | /** |
269 | * This is a doubly-linked list. | 322 | * This is a doubly-linked list. |
270 | */ | 323 | */ |
271 | struct PendingMessage *prev; | 324 | struct FragmentMessage *next; |
272 | 325 | ||
273 | /** | 326 | /** |
274 | * The pending message | 327 | * This is a doubly-linked list. |
275 | */ | 328 | */ |
276 | const char *msg; | 329 | struct FragmentMessage *prev; |
277 | 330 | ||
278 | /** | 331 | /** |
279 | * Continuation function to call once the message | 332 | * The pending message |
280 | * has been sent. Can be NULL if there is no | 333 | */ |
281 | * continuation to call. | 334 | char *msg; |
282 | */ | ||
283 | GNUNET_TRANSPORT_TransmitContinuation transmit_cont; | ||
284 | 335 | ||
285 | /** | 336 | /** |
286 | * Cls for transmit_cont | 337 | * Timeout value for the pending message. |
287 | */ | 338 | */ |
288 | void * transmit_cont_cls; | 339 | struct GNUNET_TIME_Absolute timeout; |
289 | 340 | ||
290 | /** | 341 | /** |
291 | * Timeout value for the pending message. | 342 | * Timeout value for the pending fragments. |
292 | */ | 343 | * Stores the time when the next msg fragment ack has to be received |
293 | struct GNUNET_TIME_Absolute timeout; | 344 | */ |
345 | struct GNUNET_TIME_Absolute next_ack; | ||
294 | 346 | ||
295 | /** | 347 | /** |
296 | * Timeout value for the pending fragments. | 348 | * Sorted queue with the acks received for fragments; head |
297 | * Stores the time when the last msg fragment ack was received | 349 | */ |
298 | */ | ||
299 | struct GNUNET_TIME_Absolute last_ack; | ||
300 | 350 | ||
301 | /** | 351 | struct AckQueue * head; |
302 | * Sorted queue with the acks received for fragments; head | ||
303 | */ | ||
304 | 352 | ||
305 | struct FragmentQueue * head; | 353 | /** |
354 | * Sorted queue with the acks received for fragments; tail | ||
355 | */ | ||
306 | 356 | ||
307 | /** | 357 | struct AckQueue * tail; |
308 | * Sorted queue with the acks received for fragments; tail | ||
309 | */ | ||
310 | 358 | ||
311 | struct FragmentQueue * tail; | 359 | /** |
360 | * Size of the message | ||
361 | */ | ||
362 | size_t message_size; | ||
312 | 363 | ||
313 | /** | 364 | /** |
314 | * Size of the message | 365 | * pos / next fragment number in the message, for fragmentation/segmentation, |
315 | */ | 366 | * some acks can be missing but there is still time |
316 | size_t message_size; | 367 | */ |
368 | uint32_t message_pos; | ||
317 | 369 | ||
318 | /** | ||
319 | * pos / next fragment number in the message, for fragmentation/segmentation, | ||
320 | * some acks can be missing but there is still time | ||
321 | */ | ||
322 | uint32_t message_pos; | ||
323 | }; | 370 | }; |
324 | 371 | ||
325 | |||
326 | /** | 372 | /** |
327 | * Header for messages which need fragmentation | 373 | * Header for messages which need fragmentation |
328 | */ | 374 | */ |
@@ -401,6 +447,8 @@ static int wlan_plugin_address_suggested (void *cls, | |||
401 | const void *addr, | 447 | const void *addr, |
402 | size_t addrlen); | 448 | size_t addrlen); |
403 | uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size); | 449 | uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size); |
450 | static void do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
451 | static void check_fragment_queue (struct Plugin * plugin); | ||
404 | 452 | ||
405 | /** | 453 | /** |
406 | * get the next message number, at the moment just a random one | 454 | * get the next message number, at the moment just a random one |
@@ -461,23 +509,25 @@ get_Session (struct Plugin *plugin, | |||
461 | queue->content->plugin = plugin; | 509 | queue->content->plugin = plugin; |
462 | memcpy(queue->content->addr, addr, 6); | 510 | memcpy(queue->content->addr, addr, 6); |
463 | queue->content->message_id_out = get_next_message_id(); | 511 | queue->content->message_id_out = get_next_message_id(); |
512 | queue->content->has_fragment = 0; | ||
464 | 513 | ||
465 | //queue welcome message for new sessions, not realy needed | 514 | //queue welcome message for new sessions, not realy needed |
466 | //struct WelcomeMessage welcome; | 515 | //struct WelcomeMessage welcome; |
467 | struct PendingMessage *pm; | 516 | struct PendingMessage *pm; |
468 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + GNUNET_HELLO_size(* (plugin->env->our_hello))); | 517 | pm = GNUNET_malloc (sizeof (struct PendingMessage)); |
469 | pm->msg = (const char*) &pm[1]; | 518 | pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello))); |
470 | pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello)); | 519 | pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello)); |
471 | //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello))); | 520 | //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello))); |
472 | //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); | 521 | //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); |
473 | //welcome.clientIdentity = *plugin->env->my_identity; | 522 | //welcome.clientIdentity = *plugin->env->my_identity; |
474 | memcpy (&pm[1], * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello))); | 523 | memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello))); |
475 | pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | 524 | pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; |
476 | GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head, | 525 | queue->content->pending_message = pm; |
477 | (queue->content)->pending_messages_tail, | ||
478 | pm); | ||
479 | plugin->pendingsessions ++; | 526 | plugin->pendingsessions ++; |
480 | GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Sessions, plugin->pending_Sessions_tail, plugin->pending_Sessions_tail, queue); | 527 | GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue); |
528 | |||
529 | check_fragment_queue(plugin); | ||
530 | |||
481 | return queue->content; | 531 | return queue->content; |
482 | 532 | ||
483 | } | 533 | } |
@@ -520,8 +570,8 @@ queue_Session (struct Plugin *plugin, | |||
520 | 570 | ||
521 | //TODO doxigen | 571 | //TODO doxigen |
522 | static void | 572 | static void |
523 | free_acks (struct PendingMessage * pm){ | 573 | free_acks (struct FragmentMessage * pm){ |
524 | struct FragmentQueue * fq; | 574 | struct AckQueue * fq; |
525 | while (pm->head != NULL){ | 575 | while (pm->head != NULL){ |
526 | fq = pm->head; | 576 | fq = pm->head; |
527 | GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq); | 577 | GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq); |
@@ -529,6 +579,181 @@ free_acks (struct PendingMessage * pm){ | |||
529 | } | 579 | } |
530 | } | 580 | } |
531 | 581 | ||
582 | //TODO doxigen | ||
583 | static void | ||
584 | delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc){ | ||
585 | struct Plugin * plugin = cls; | ||
586 | plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; | ||
587 | |||
588 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
589 | return; | ||
590 | |||
591 | // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg | ||
592 | plugin->server_write_task | ||
593 | = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL, | ||
594 | plugin->server_stdin_handle, | ||
595 | &do_transmit, | ||
596 | plugin); | ||
597 | } | ||
598 | |||
599 | |||
600 | //TODO doxigen | ||
601 | struct GNUNET_TIME_Relative | ||
602 | get_next_frag_timeout (struct FragmentMessage * fm) | ||
603 | { | ||
604 | return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout)); | ||
605 | } | ||
606 | |||
607 | //TODO doxigen | ||
608 | /** | ||
609 | * Function to get the timeout value for acks for this session | ||
610 | */ | ||
611 | |||
612 | struct GNUNET_TIME_Relative | ||
613 | get_ack_timeout (struct FragmentMessage * fm){ | ||
614 | struct GNUNET_TIME_Relative timeout; | ||
615 | timeout.rel_value = FRAGMENT_TIMEOUT; | ||
616 | return timeout; | ||
617 | } | ||
618 | |||
619 | //TODO doxigen | ||
620 | /** | ||
621 | * Function to set the timer for the next timeout of the fragment queue | ||
622 | */ | ||
623 | static void | ||
624 | check_next_fragment_timeout (struct Plugin * plugin){ | ||
625 | struct FragmentMessage * fm; | ||
626 | if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK){ | ||
627 | GNUNET_SCHEDULER_cancel(plugin->server_write_task); | ||
628 | } | ||
629 | fm = plugin->pending_Fragment_Messages_head; | ||
630 | if (fm != NULL){ | ||
631 | plugin->server_write_task = GNUNET_SCHEDULER_add_delayed(get_next_frag_timeout(fm), &delay_fragment_task, plugin); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | //TODO doxigen | ||
636 | /** | ||
637 | * Function to get the next queued Session, removes the session from the queue | ||
638 | */ | ||
639 | |||
640 | static struct Session * | ||
641 | get_next_queue_Session (struct Plugin * plugin){ | ||
642 | struct Session * session; | ||
643 | struct Sessionqueue * sessionqueue; | ||
644 | struct Sessionqueue * sessionqueue_alt; | ||
645 | struct PendingMessage * pm; | ||
646 | sessionqueue = plugin->pending_Sessions; | ||
647 | while (sessionqueue != NULL){ | ||
648 | session = sessionqueue->content; | ||
649 | pm = session->pending_message; | ||
650 | |||
651 | //check for message timeout | ||
652 | if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){ | ||
653 | //check if session has no message in the fragment queue | ||
654 | if (! session->has_fragment){ | ||
655 | plugin->pendingsessions --; | ||
656 | GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, | ||
657 | plugin->pending_Sessions_tail, sessionqueue); | ||
658 | GNUNET_free(sessionqueue); | ||
659 | |||
660 | return session; | ||
661 | } else { | ||
662 | sessionqueue = sessionqueue->next; | ||
663 | } | ||
664 | } else { | ||
665 | |||
666 | session->pending_message = NULL; | ||
667 | //call the cont func that it did not work | ||
668 | if (pm->transmit_cont != NULL) | ||
669 | pm->transmit_cont (pm->transmit_cont_cls, | ||
670 | &(session->target), GNUNET_SYSERR); | ||
671 | GNUNET_free(pm->msg); | ||
672 | GNUNET_free(pm); | ||
673 | |||
674 | sessionqueue_alt = sessionqueue; | ||
675 | sessionqueue = sessionqueue->next; | ||
676 | plugin->pendingsessions --; | ||
677 | GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, | ||
678 | plugin->pending_Sessions_tail, sessionqueue_alt); | ||
679 | |||
680 | GNUNET_free(sessionqueue_alt); | ||
681 | |||
682 | } | ||
683 | |||
684 | |||
685 | } | ||
686 | return NULL; | ||
687 | } | ||
688 | |||
689 | //TODO doxigen | ||
690 | /** | ||
691 | * Function to sort the message into the message fragment queue | ||
692 | */ | ||
693 | static void | ||
694 | sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){ | ||
695 | struct FragmentMessage * fm2; | ||
696 | //sort into the list at the right position | ||
697 | |||
698 | fm2 = plugin->pending_Fragment_Messages_head; | ||
699 | |||
700 | while (fm2 != NULL){ | ||
701 | if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){ | ||
702 | break; | ||
703 | } else { | ||
704 | fm2 = fm2->next; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head, | ||
709 | plugin->pending_Fragment_Messages_tail,fm2,fm); | ||
710 | } | ||
711 | |||
712 | //TODO doxigen | ||
713 | /** | ||
714 | * Function to check if there is some space in the fragment queue | ||
715 | */ | ||
716 | |||
717 | static void | ||
718 | check_fragment_queue (struct Plugin * plugin){ | ||
719 | struct Session * session; | ||
720 | struct FragmentMessage * fm; | ||
721 | |||
722 | struct PendingMessage * pm; | ||
723 | |||
724 | if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){ | ||
725 | session = get_next_queue_Session(plugin); | ||
726 | if (session != NULL){ | ||
727 | pm = session->pending_message; | ||
728 | session->pending_message = NULL; | ||
729 | session->has_fragment = 1; | ||
730 | GNUNET_assert(pm != NULL); | ||
731 | |||
732 | fm = GNUNET_malloc(sizeof(struct FragmentMessage)); | ||
733 | fm->message_size = pm->message_size; | ||
734 | fm->msg = pm->msg; | ||
735 | fm->session = session; | ||
736 | fm->timeout.abs_value = pm->timeout.abs_value; | ||
737 | fm->message_pos = 0; | ||
738 | fm->next_ack = GNUNET_TIME_absolute_get(); | ||
739 | |||
740 | if (pm->transmit_cont != NULL) | ||
741 | pm->transmit_cont (pm->transmit_cont_cls, | ||
742 | &(session->target), GNUNET_OK); | ||
743 | GNUNET_free(pm); | ||
744 | |||
745 | sort_fragment_into_queue(plugin,fm); | ||
746 | plugin->pending_fragment_messages ++; | ||
747 | |||
748 | //generate new message id | ||
749 | session->message_id_out = get_next_message_id(); | ||
750 | |||
751 | //check if timeout changed | ||
752 | check_next_fragment_timeout(plugin); | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | |||
532 | /** | 757 | /** |
533 | * Function called to when wlan helper is ready to get some data | 758 | * Function called to when wlan helper is ready to get some data |
534 | * | 759 | * |
@@ -539,15 +764,17 @@ free_acks (struct PendingMessage * pm){ | |||
539 | static void | 764 | static void |
540 | do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 765 | do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
541 | { | 766 | { |
767 | |||
542 | struct Plugin * plugin = cls; | 768 | struct Plugin * plugin = cls; |
769 | plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; | ||
770 | |||
543 | ssize_t bytes; | 771 | ssize_t bytes; |
544 | 772 | ||
545 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | 773 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) |
546 | return; | 774 | return; |
547 | 775 | ||
548 | struct Session * session; | 776 | struct Session * session; |
549 | struct Sessionqueue * queue; | 777 | struct FragmentMessage * fm; |
550 | struct PendingMessage * pm; | ||
551 | struct IeeeHeader * wlanheader; | 778 | struct IeeeHeader * wlanheader; |
552 | struct RadiotapHeader * radioHeader; | 779 | struct RadiotapHeader * radioHeader; |
553 | struct GNUNET_MessageHeader * msgheader; | 780 | struct GNUNET_MessageHeader * msgheader; |
@@ -556,289 +783,143 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
556 | const char * copystart = NULL; | 783 | const char * copystart = NULL; |
557 | uint16_t copysize = 0; | 784 | uint16_t copysize = 0; |
558 | uint copyoffset = 0; | 785 | uint copyoffset = 0; |
559 | struct FragmentQueue * akt = NULL; | 786 | struct AckQueue * akt = NULL; |
560 | int exit = 0; | 787 | //int exit = 0; |
561 | |||
562 | int i = 0; | ||
563 | |||
564 | struct GNUNET_TIME_Absolute nextsend; | ||
565 | struct GNUNET_TIME_Relative timeout; | ||
566 | struct Sessionqueue * nextsession = NULL; | ||
567 | |||
568 | timeout.rel_value = FRAGMENT_TIMEOUT; | ||
569 | nextsend = GNUNET_TIME_absolute_get_forever(); | ||
570 | 788 | ||
571 | queue = plugin->pending_Sessions; | 789 | fm = plugin->pending_Fragment_Messages_head; |
572 | 790 | GNUNET_assert(fm != NULL); | |
573 | // check if the are some pending sessions/messages ... | 791 | session = fm->session; |
574 | GNUNET_assert(queue != NULL); | ||
575 | |||
576 | session = queue->content; | ||
577 | GNUNET_assert(session != NULL); | 792 | GNUNET_assert(session != NULL); |
578 | 793 | ||
579 | pm = session->pending_messages_head; | 794 | // test if message timed out |
580 | GNUNET_assert(pm != NULL); | 795 | if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){ |
581 | 796 | free_acks(fm); | |
582 | // get next valid session | 797 | GNUNET_assert(plugin->pending_fragment_messages > 0); |
583 | // check if this session is only waiting to receive the acks for an already send fragments to finish it | 798 | plugin->pending_fragment_messages --; |
584 | // timeout is not reached | 799 | GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head, |
585 | for (i = 0; i < plugin->pendingsessions; i++){ | 800 | plugin->pending_Fragment_Messages_tail, fm); |
586 | |||
587 | // check if the are some pending sessions/messages ... | ||
588 | GNUNET_assert(queue != NULL); | ||
589 | 801 | ||
590 | session = queue->content; | 802 | GNUNET_free(fm->msg); |
591 | GNUNET_assert(session != NULL); | ||
592 | 803 | ||
593 | pm = session->pending_messages_head; | 804 | GNUNET_free(fm); |
594 | GNUNET_assert(pm != NULL); | 805 | check_fragment_queue(plugin); |
595 | 806 | } else { | |
596 | //save next session | ||
597 | nextsession = queue->next; | ||
598 | // test if message timed out | ||
599 | while (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value == 0){ | ||
600 | //remove message | ||
601 | //free the acks | ||
602 | free_acks (pm); | ||
603 | //call the cont func that it did not work | ||
604 | if (pm->transmit_cont != NULL) | ||
605 | pm->transmit_cont (pm->transmit_cont_cls, | ||
606 | &(session->target), GNUNET_SYSERR); | ||
607 | //remove the message | ||
608 | GNUNET_CONTAINER_DLL_remove (session->pending_messages_head, | ||
609 | session->pending_messages_tail, | ||
610 | pm); | ||
611 | GNUNET_free(pm); | ||
612 | |||
613 | //test if there are no more messages pending for this session | ||
614 | if (session->pending_messages_head == NULL){ | ||
615 | |||
616 | //test if tail is null too | ||
617 | GNUNET_assert(session->pending_messages_tail == NULL); | ||
618 | |||
619 | plugin->pendingsessions --; | ||
620 | GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, plugin->pending_Sessions_tail, queue); | ||
621 | GNUNET_free(queue); | ||
622 | queue = NULL; | ||
623 | break; | ||
624 | |||
625 | } else { | ||
626 | pm = session->pending_messages_head; | ||
627 | } | ||
628 | |||
629 | } | ||
630 | // restore next session if necessary | ||
631 | if (queue == NULL){ | ||
632 | queue = nextsession; | ||
633 | nextsession = NULL; | ||
634 | //there are no more messages in this session | ||
635 | continue; | ||
636 | } | ||
637 | nextsession = NULL; | ||
638 | |||
639 | // test if retransmit is needed | ||
640 | if (GNUNET_TIME_absolute_get_duration(pm->last_ack).rel_value < FRAGMENT_TIMEOUT) { | ||
641 | // get last offset for this message | ||
642 | copyoffset = pm->message_size /(WLAN_MTU - sizeof(struct FragmentationHeader)); | ||
643 | // one more is the end | ||
644 | copyoffset ++; | ||
645 | // test if it is not the end | ||
646 | if (copyoffset > pm->message_pos){ | ||
647 | nextsession = queue; | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | nextsend = GNUNET_TIME_absolute_min(GNUNET_TIME_absolute_add(pm->last_ack, timeout), nextsend); | ||
652 | |||
653 | GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, plugin->pending_Sessions_tail, queue); | ||
654 | //insert at the tail | ||
655 | GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions, | ||
656 | plugin->pending_Sessions_tail, | ||
657 | plugin->pending_Sessions_tail, queue); | ||
658 | |||
659 | //get next pending session | ||
660 | queue = queue->next; | ||
661 | |||
662 | } else { | ||
663 | // retransmit | ||
664 | nextsession = queue; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | 807 | ||
808 | if (fm->message_size > WLAN_MTU) { | ||
809 | size += sizeof(struct FragmentationHeader); | ||
810 | // check/set for retransmission | ||
811 | if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) { | ||
812 | |||
813 | // be positive and try again later :-D | ||
814 | fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm)); | ||
815 | // find first missing fragment | ||
816 | akt = fm->head; | ||
817 | fm->message_pos = 0; | ||
818 | |||
819 | //test if ack 0 was already received | ||
820 | while (akt != NULL){ | ||
821 | //if fragment is present, take next | ||
822 | if (akt->fragment_num == fm->message_pos) { | ||
823 | fm->message_pos ++; | ||
824 | } | ||
825 | //next ack is bigger then the fragment number | ||
826 | //in case there is something like this: (acks) 1, 2, 5, 6, ... | ||
827 | //and we send 3 again, the next number should be 4 | ||
828 | else if (akt->fragment_num > fm->message_pos) { | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | akt = akt->next; | ||
669 | 833 | ||
670 | //test if there is one session to send something | 834 | } |
671 | if (nextsession != NULL){ | ||
672 | queue = nextsession; | ||
673 | 835 | ||
674 | // check if the are some pending sessions/messages ... | ||
675 | GNUNET_assert(queue != NULL); | ||
676 | 836 | ||
677 | session = queue->content; | 837 | } |
678 | GNUNET_assert(session != NULL); | ||
679 | 838 | ||
680 | pm = session->pending_messages_head; | 839 | copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos; |
681 | GNUNET_assert(pm != NULL); | 840 | fragheader.fragment_off_or_num = htons(fm->message_pos); |
682 | } else { | 841 | fragheader.message_id = htonl(session->message_id_out); |
683 | //nothing to send at the moment | ||
684 | plugin->server_read_task = | ||
685 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(nextsend), | ||
686 | &do_transmit, plugin); | ||
687 | 842 | ||
688 | } | 843 | // start should be smaller then the packet size |
844 | GNUNET_assert(copyoffset < fm->message_size); | ||
845 | copystart = fm->msg + copyoffset; | ||
689 | 846 | ||
847 | //size of the fragment is either the MTU - overhead | ||
848 | //or the missing part of the message in case this is the last fragment | ||
849 | copysize = GNUNET_MIN(fm->message_size - copyoffset, | ||
850 | WLAN_MTU - sizeof(struct FragmentationHeader)); | ||
851 | fragheader.header.size = htons(copysize); | ||
852 | fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT; | ||
690 | 853 | ||
691 | 854 | ||
692 | if (pm->message_size > WLAN_MTU) { | 855 | //get the next missing fragment |
693 | size += sizeof(struct FragmentationHeader); | 856 | akt = fm->head; |
694 | // check for retransmission | 857 | fm->message_pos ++; |
695 | if (GNUNET_TIME_absolute_get_duration(pm->last_ack).rel_value > FRAGMENT_TIMEOUT) { | ||
696 | // TODO retransmit | ||
697 | // be positive and try again later :-D | ||
698 | pm->last_ack = GNUNET_TIME_absolute_get(); | ||
699 | // find first missing fragment | ||
700 | exit = 0; | ||
701 | akt = pm->head; | ||
702 | pm->message_pos = 0; | ||
703 | 858 | ||
704 | //test if ack 0 was already received | 859 | //test if ack was already received |
705 | while (akt != NULL){ | 860 | while (akt != NULL){ |
706 | //if fragment is present, take next | 861 | //if fragment is present, take next |
707 | if (akt->fragment_num == pm->message_pos) { | 862 | if (akt->fragment_num == fm->message_pos) { |
708 | pm->message_pos ++; | 863 | fm->message_pos ++; |
709 | } | 864 | } |
710 | //next ack is bigger then the fragment number | 865 | //next ack is bigger then the fragment number |
711 | //in case there is something like this: (acks) 1, 2, 5, 6, ... | 866 | //in case there is something like this: (acks) 1, 2, 5, 6, ... |
712 | //and we send 3 again, the next number should be 4 | 867 | //and we send 3 again, the next number should be 4 |
713 | if (akt->fragment_num > pm->message_pos) { | 868 | else if (akt->fragment_num > fm->message_pos) { |
714 | break; | 869 | break; |
715 | } | 870 | } |
716 | 871 | ||
717 | akt = akt->next; | 872 | akt = akt->next; |
718 | |||
719 | } | 873 | } |
874 | } else { | ||
875 | // there is no need to split | ||
876 | copystart = fm->msg; | ||
877 | copysize = fm->message_size; | ||
878 | } | ||
720 | 879 | ||
880 | size += copysize; | ||
881 | size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader) | ||
882 | + sizeof(struct GNUNET_MessageHeader); | ||
883 | msgheader = GNUNET_malloc(size); | ||
884 | msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader)); | ||
885 | msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA; | ||
721 | 886 | ||
722 | } | 887 | radioHeader = (struct RadiotapHeader*) &msgheader[1]; |
888 | getRadiotapHeader(radioHeader); | ||
723 | 889 | ||
724 | copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * pm->message_pos; | 890 | wlanheader = (struct IeeeHeader *) &radioHeader[1]; |
725 | fragheader.fragment_off_or_num = pm->message_pos; | 891 | getWlanHeader(wlanheader); |
726 | fragheader.message_id = session->message_id_out; | ||
727 | |||
728 | // start should be smaller then the packet size | ||
729 | //TODO send some other data if everything was send but not all acks are present | ||
730 | GNUNET_assert(copyoffset < pm->message_size); | ||
731 | copystart = pm->msg + copyoffset; | ||
732 | |||
733 | //size of the fragment is either the MTU - overhead | ||
734 | //or the missing part of the message in case this is the last fragment | ||
735 | copysize = GNUNET_MIN(pm->message_size - copyoffset, | ||
736 | WLAN_MTU - sizeof(struct FragmentationHeader)); | ||
737 | fragheader.header.size = copysize; | ||
738 | fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT; | ||
739 | |||
740 | //get the next missing fragment | ||
741 | exit = 0; | ||
742 | akt = pm->head; | ||
743 | pm->message_pos ++; | ||
744 | |||
745 | //test if ack was already received | ||
746 | while (akt != NULL){ | ||
747 | //if fragment is present, take next | ||
748 | if (akt->fragment_num == pm->message_pos) { | ||
749 | pm->message_pos ++; | ||
750 | } | ||
751 | //next ack is bigger then the fragment number | ||
752 | //in case there is something like this: (acks) 1, 2, 5, 6, ... | ||
753 | //and we send 3 again, the next number should be 4 | ||
754 | if (akt->fragment_num > pm->message_pos) { | ||
755 | break; | ||
756 | } | ||
757 | |||
758 | akt = akt->next; | ||
759 | } | ||
760 | 892 | ||
761 | 893 | ||
894 | //could be faster if content is just send and not copyed before | ||
895 | //fragmentheader is needed | ||
896 | if (fm->message_size > WLAN_MTU){ | ||
897 | fragheader.message_crc = htons(getcrc16(copystart, copysize)); | ||
898 | memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader)); | ||
899 | memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize); | ||
762 | } else { | 900 | } else { |
763 | // there is no need to split | 901 | memcpy(&wlanheader[1],copystart,copysize); |
764 | copystart = pm->msg; | ||
765 | copysize = pm->message_size; | ||
766 | } | 902 | } |
767 | size += copysize; | ||
768 | size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader) | ||
769 | + sizeof(struct GNUNET_MessageHeader); | ||
770 | msgheader = GNUNET_malloc(size); | ||
771 | msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader)); | ||
772 | msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA; | ||
773 | |||
774 | radioHeader = (struct RadiotapHeader*) &msgheader[1]; | ||
775 | getRadiotapHeader(radioHeader); | ||
776 | |||
777 | wlanheader = (struct IeeeHeader *) &radioHeader[1]; | ||
778 | getWlanHeader(wlanheader); | ||
779 | |||
780 | |||
781 | //could be faster if content is just send and not copyed before | ||
782 | //fragmentheader is needed | ||
783 | if (pm->message_size > WLAN_MTU){ | ||
784 | fragheader.message_crc = getcrc16(copystart, copysize); | ||
785 | memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader)); | ||
786 | memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize); | ||
787 | } else { | ||
788 | memcpy(&wlanheader[1],copystart,copysize); | ||
789 | } | ||
790 | |||
791 | bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size); | ||
792 | |||
793 | |||
794 | |||
795 | |||
796 | 903 | ||
904 | bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size); | ||
905 | GNUNET_assert(bytes == size); | ||
797 | 906 | ||
907 | //check if this was the last fragment of this message, if true then queue at the end of the list | ||
908 | if (copysize + copyoffset >= fm->message_size){ | ||
909 | GNUNET_assert(copysize + copyoffset == fm->message_size); | ||
798 | 910 | ||
911 | GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head, | ||
912 | plugin->pending_Fragment_Messages_tail, fm); | ||
799 | 913 | ||
800 | if (bytes < 1) | 914 | GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head, |
801 | { | 915 | plugin->pending_Fragment_Messages_tail, fm); |
802 | return; | 916 | // if fragments have opimized timeouts |
803 | } | 917 | //sort_fragment_into_queue(plugin,fm); |
804 | |||
805 | //plugin->server_read_task = | ||
806 | //GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
807 | // plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin); | ||
808 | |||
809 | } | ||
810 | |||
811 | |||
812 | |||
813 | /** | ||
814 | * If we have pending messages, ask the server to | ||
815 | * transmit them (schedule the respective tasks, etc.) | ||
816 | * | ||
817 | * @param Plugin env to get everything needed | ||
818 | */ | ||
819 | static void | ||
820 | process_pending_messages (struct Plugin * plugin) | ||
821 | { | ||
822 | struct Sessionqueue * queue; | ||
823 | struct Session * session; | ||
824 | 918 | ||
825 | if (plugin->pending_Sessions == NULL) | 919 | } |
826 | return; | 920 | check_next_fragment_timeout(plugin); |
827 | |||
828 | queue = plugin->pending_Sessions; | ||
829 | //contet should not be empty | ||
830 | GNUNET_assert(queue->content != NULL); | ||
831 | |||
832 | session = queue->content; | ||
833 | //pending sessions should have some msg | ||
834 | GNUNET_assert(session->pending_messages_head != NULL); | ||
835 | 921 | ||
836 | // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg | 922 | } |
837 | plugin->server_write_task | ||
838 | = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL, | ||
839 | plugin->server_stdin_handle, | ||
840 | &do_transmit, | ||
841 | plugin); | ||
842 | } | 923 | } |
843 | 924 | ||
844 | 925 | ||
@@ -940,48 +1021,24 @@ wlan_plugin_send (void *cls, | |||
940 | queue_Session(plugin, session); | 1021 | queue_Session(plugin, session); |
941 | 1022 | ||
942 | //queue message in session | 1023 | //queue message in session |
943 | newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size + sizeof(struct WlanHeader)); | 1024 | if (session->pending_message == NULL){ |
944 | newmsg->msg = (const char*) &newmsg[1]; | 1025 | newmsg = GNUNET_malloc(sizeof(struct PendingMessage)); |
945 | wlanheader = (struct WlanHeader *) &newmsg[1]; | 1026 | (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader)); |
946 | //copy msg to buffer, not fragmented / segmented yet, but with message header | 1027 | wlanheader = (struct WlanHeader *) newmsg->msg; |
947 | wlanheader->header.size = msgbuf_size; | 1028 | //copy msg to buffer, not fragmented / segmented yet, but with message header |
948 | wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA; | 1029 | wlanheader->header.size = htons(msgbuf_size); |
949 | wlanheader->target = *target; | 1030 | wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA; |
950 | wlanheader->crc = getcrc32(msgbuf, msgbuf_size); | 1031 | wlanheader->target = *target; |
951 | memcpy(&wlanheader[1], msgbuf, msgbuf_size); | 1032 | wlanheader->crc = getcrc32(msgbuf, msgbuf_size); |
952 | newmsg->transmit_cont = cont; | 1033 | memcpy(&wlanheader[1], msgbuf, msgbuf_size); |
953 | newmsg->transmit_cont_cls = cont_cls; | 1034 | newmsg->transmit_cont = cont; |
954 | newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout); | 1035 | newmsg->transmit_cont_cls = cont_cls; |
955 | newmsg->message_pos = 0; | 1036 | newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout); |
956 | newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader); | 1037 | newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader); |
957 | newmsg->next = NULL; | ||
958 | |||
959 | //check if queue is empty | ||
960 | struct PendingMessage * tailmsg; | ||
961 | tailmsg = session->pending_messages_tail; | ||
962 | |||
963 | //new tail is the new msg | ||
964 | session->pending_messages_tail = newmsg; | ||
965 | newmsg->prev = tailmsg; | ||
966 | |||
967 | //test if tail was not NULL (queue is empty) | ||
968 | if (tailmsg == NULL){ | ||
969 | // head should be NULL too | ||
970 | GNUNET_assert(session->pending_messages_head == NULL); | ||
971 | |||
972 | session->pending_messages_head = newmsg; | ||
973 | |||
974 | } else { | 1038 | } else { |
975 | //next at the tail should be NULL | 1039 | //TODO if message is send while hello is still pending, other cases should not occur |
976 | GNUNET_assert(tailmsg->next == NULL); | ||
977 | |||
978 | //queue the msg | ||
979 | tailmsg->next = newmsg; | ||
980 | } | 1040 | } |
981 | 1041 | check_fragment_queue(plugin); | |
982 | process_pending_messages(plugin); | ||
983 | |||
984 | |||
985 | //FIXME not the correct size | 1042 | //FIXME not the correct size |
986 | return msgbuf_size; | 1043 | return msgbuf_size; |
987 | 1044 | ||
@@ -1012,15 +1069,11 @@ wlan_plugin_disconnect (void *cls, | |||
1012 | GNUNET_assert (queue->content == NULL); | 1069 | GNUNET_assert (queue->content == NULL); |
1013 | if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0) | 1070 | if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0) |
1014 | { | 1071 | { |
1015 | // sesion found | 1072 | // session found |
1016 | // remove PendingMessage | 1073 | // remove PendingMessage |
1017 | while (queue->content->pending_messages_head != NULL){ | 1074 | pm = queue->content->pending_message; |
1018 | pm = queue->content->pending_messages_head; | 1075 | GNUNET_free(pm->msg); |
1019 | free_acks(pm); | 1076 | GNUNET_free(pm); |
1020 | GNUNET_CONTAINER_DLL_remove(queue->content->pending_messages_head,queue->content->pending_messages_tail, pm); | ||
1021 | GNUNET_free(pm); | ||
1022 | |||
1023 | } | ||
1024 | 1077 | ||
1025 | GNUNET_free(queue->content); | 1078 | GNUNET_free(queue->content); |
1026 | GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue); | 1079 | GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue); |
@@ -1295,6 +1348,8 @@ gnunet_plugin_transport_wlan_init (void *cls) | |||
1295 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 1348 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
1296 | plugin->env = env; | 1349 | plugin->env = env; |
1297 | plugin->pendingsessions = 0; | 1350 | plugin->pendingsessions = 0; |
1351 | plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; | ||
1352 | plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; | ||
1298 | 1353 | ||
1299 | wlan_transport_start_wlan_helper(plugin); | 1354 | wlan_transport_start_wlan_helper(plugin); |
1300 | plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin); | 1355 | plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin); |
@@ -1310,6 +1365,7 @@ gnunet_plugin_transport_wlan_init (void *cls) | |||
1310 | api->check_address = &wlan_plugin_address_suggested; | 1365 | api->check_address = &wlan_plugin_address_suggested; |
1311 | api->address_to_string = &wlan_plugin_address_to_string; | 1366 | api->address_to_string = &wlan_plugin_address_to_string; |
1312 | 1367 | ||
1368 | |||
1313 | start_next_message_id(); | 1369 | start_next_message_id(); |
1314 | 1370 | ||
1315 | return api; | 1371 | return api; |