aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_wlan.c
diff options
context:
space:
mode:
authorDavid Brodski <david@brodski.eu>2010-11-09 22:24:58 +0000
committerDavid Brodski <david@brodski.eu>2010-11-09 22:24:58 +0000
commit3db08333ec2b301cc8f204ad74f5aa8a25e3426f (patch)
treeeaee71e79c7f8bbc91e0c21842bd18af792b159d /src/transport/plugin_transport_wlan.c
parente0dd7bcc0b9417f5bbd2bf910ec8c6a967a66c77 (diff)
downloadgnunet-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.c798
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
180struct FragmentQueue 199struct 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 */
210struct 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 */
190struct Session 245struct 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 */ 313struct FragmentMessage
260struct 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);
403uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size); 449uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
450static void do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
451static 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
522static void 572static void
523free_acks (struct PendingMessage * pm){ 573free_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
583static void
584delay_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
601struct GNUNET_TIME_Relative
602get_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
612struct GNUNET_TIME_Relative
613get_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 */
623static void
624check_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
640static struct Session *
641get_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 */
693static void
694sort_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
717static void
718check_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){
539static void 764static void
540do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 765do_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 */
819static void
820process_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;