aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Brodski <david@brodski.eu>2010-10-05 21:46:44 +0000
committerDavid Brodski <david@brodski.eu>2010-10-05 21:46:44 +0000
commit24be41ca6f5987a964ed215f5419aaeeef7a0f62 (patch)
treeed47251775e12e98202a4247238428b66a7a69af /src
parent49f64cbc932d5978252a6b23e7b85b950c51199d (diff)
downloadgnunet-24be41ca6f5987a964ed215f5419aaeeef7a0f62.tar.gz
gnunet-24be41ca6f5987a964ed215f5419aaeeef7a0f62.zip
Sending of data over wlan added; fragmentation added
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_protocols.h7
-rw-r--r--src/transport/plugin_transport_wlan.c288
2 files changed, 258 insertions, 37 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index a8994da48..3de18f8d1 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -670,12 +670,17 @@ extern "C"
670 670
671/** 671/**
672 * Type of messages for data over the wlan 672 * Type of messages for data over the wlan
673 *
674 */ 673 */
675 674
676#define GNUNET_MESSAGE_TYPE_WLAN_DATA 198 675#define GNUNET_MESSAGE_TYPE_WLAN_DATA 198
677 676
678/** 677/**
678 * Fragment of a message
679 */
680
681#define GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT 199
682
683/**
679 * Type of messages to query the local service-dns 684 * Type of messages to query the local service-dns
680 */ 685 */
681#define GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS 205 686#define GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS 205
diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c
index 963829218..d0d12d09d 100644
--- a/src/transport/plugin_transport_wlan.c
+++ b/src/transport/plugin_transport_wlan.c
@@ -25,6 +25,7 @@
25 */ 25 */
26 26
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_hello_lib.h"
28#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
29#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
@@ -40,6 +41,13 @@
40 */ 41 */
41#define WLAN_MTU 3000 42#define WLAN_MTU 3000
42 43
44/**
45 * Time until retransmission of a fragment in ms
46 */
47
48#define FRAGMENT_TIMEOUT 1000
49
50
43#define DEBUG_wlan GNUNET_NO 51#define DEBUG_wlan GNUNET_NO
44 52
45/** 53/**
@@ -147,6 +155,7 @@ struct Plugin
147 155
148}; 156};
149 157
158//TODO doxigen
150 159
151struct Sessionqueue 160struct Sessionqueue
152{ 161{
@@ -155,6 +164,15 @@ struct Sessionqueue
155 struct Session * content; 164 struct Session * content;
156}; 165};
157 166
167//TODO doxigen
168
169struct FragmentQueue
170{
171 struct FragmentQueue * next;
172 struct FragmentQueue * prev;
173 int fragment_num;
174};
175
158/** 176/**
159 * Session handle for connections. 177 * Session handle for connections.
160 */ 178 */
@@ -212,14 +230,14 @@ struct Session
212 struct GNUNET_TIME_Absolute last_activity; 230 struct GNUNET_TIME_Absolute last_activity;
213 231
214 /** 232 /**
215 * number of message, to distinguish between the messages 233 * current number for message incoming , to distinguish between the messages
216 */ 234 */
217 uint16_t message_num_in; 235 uint32_t message_id_in;
218 236
219 /** 237 /**
220 * number of message, to distinguish between the messages 238 * current number for message outgoing, to distinguish between the messages
221 */ 239 */
222 uint16_t message_num_out; 240 uint32_t message_id_out;
223 241
224 242
225}; 243};
@@ -264,14 +282,33 @@ struct PendingMessage
264 struct GNUNET_TIME_Absolute timeout; 282 struct GNUNET_TIME_Absolute timeout;
265 283
266 /** 284 /**
285 * Timeout value for the pending fragments.
286 * Stores the time when the last msg fragment ack was received
287 */
288 struct GNUNET_TIME_Absolute last_ack;
289
290 /**
291 * Sorted queue with the acks received for fragments; head
292 */
293
294 struct FragmentQueue * head;
295
296 /**
297 * Sorted queue with the acks received for fragments; tail
298 */
299
300 struct FragmentQueue * tail;
301
302 /**
267 * Size of the message 303 * Size of the message
268 */ 304 */
269 size_t message_size; 305 size_t message_size;
270 306
271 /** 307 /**
272 * pos in the message, for fragmentation/segmentation 308 * pos / next fragment number in the message, for fragmentation/segmentation,
309 * some acks can be missing but there is still time
273 */ 310 */
274 size_t message_pos; 311 uint32_t message_pos;
275}; 312};
276 313
277 314
@@ -345,18 +382,48 @@ struct FragmentationHeader
345 382
346}; 383};
347 384
348enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 }; 385//enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
349 386
350int getRadiotapHeader (struct RadiotapHeader * Header); 387int getRadiotapHeader (struct RadiotapHeader * Header);
351int getWlanHeader (struct IeeeHeader * Header); 388int getWlanHeader (struct IeeeHeader * Header);
352static int wlan_plugin_address_suggested (void *cls, 389static int wlan_plugin_address_suggested (void *cls,
353 const void *addr, 390 const void *addr,
354 size_t addrlen); 391 size_t addrlen);
392uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
393
355/** 394/**
356 * get Session from address 395 * get the next message number, at the moment just a random one
357 * 396 *
358 */ 397 */
359 398
399uint32_t
400get_next_message_id()
401{
402 // FIXME find good random generator
403 if (RAND_MAX < UINT32_MAX){
404 return (random() * random()) % UINT32_MAX;
405 } else {
406 return random() % UINT32_MAX;
407 }
408}
409
410/**
411 * start next message number generator
412 */
413
414void
415start_next_message_id()
416{
417 //FIXME not good
418 srand(GNUNET_TIME_absolute_get().value);
419}
420
421
422/**
423 * get Session from address
424 *
425 */
426//TODO doxigen
360//TODO add other possibilities to find the right session (are there other?) 427//TODO add other possibilities to find the right session (are there other?)
361static struct Session * 428static struct Session *
362get_Session (struct Plugin *plugin, 429get_Session (struct Plugin *plugin,
@@ -365,6 +432,8 @@ get_Session (struct Plugin *plugin,
365 struct Sessionqueue * queue = plugin->all_Sessions; 432 struct Sessionqueue * queue = plugin->all_Sessions;
366 struct Sessionqueue * lastitem = NULL; 433 struct Sessionqueue * lastitem = NULL;
367 434
435
436 //just look at all the session for the needed one
368 while (queue != NULL){ 437 while (queue != NULL){
369 // content is never NULL 438 // content is never NULL
370 GNUNET_assert (queue->content == NULL); 439 GNUNET_assert (queue->content == NULL);
@@ -392,17 +461,18 @@ get_Session (struct Plugin *plugin,
392 queue->content = GNUNET_malloc (sizeof (struct Session)); 461 queue->content = GNUNET_malloc (sizeof (struct Session));
393 queue->content->plugin = plugin; 462 queue->content->plugin = plugin;
394 memcpy(queue->content->addr, addr, 6); 463 memcpy(queue->content->addr, addr, 6);
464 queue->content->message_id_out = get_next_message_id();
395 465
396 //queue welcome 466 //queue welcome message for new sessions, not realy needed
397 struct WelcomeMessage welcome; 467 //struct WelcomeMessage welcome;
398 struct PendingMessage *pm; 468 struct PendingMessage *pm;
399 pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct WelcomeMessage)); 469 pm = GNUNET_malloc (sizeof (struct PendingMessage) + GNUNET_HELLO_size(* (plugin->env->our_hello)));
400 pm->msg = (const char*) &pm[1]; 470 pm->msg = (const char*) &pm[1];
401 pm->message_size = sizeof (struct WelcomeMessage); 471 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
402 welcome.header.size = htons (sizeof (struct WelcomeMessage)); 472 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
403 welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); 473 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
404 welcome.clientIdentity = *plugin->env->my_identity; 474 //welcome.clientIdentity = *plugin->env->my_identity;
405 memcpy (&pm[1], &welcome, sizeof (welcome)); 475 memcpy (&pm[1], * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
406 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; 476 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
407 GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head, 477 GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head,
408 (queue->content)->pending_messages_tail, 478 (queue->content)->pending_messages_tail,
@@ -415,7 +485,7 @@ get_Session (struct Plugin *plugin,
415/** 485/**
416 * Queue the session to send data 486 * Queue the session to send data
417 */ 487 */
418 488//TODO doxigen
419static void 489static void
420queue_Session (struct Plugin *plugin, 490queue_Session (struct Plugin *plugin,
421 struct Session * session) 491 struct Session * session)
@@ -472,7 +542,13 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
472 struct IeeeHeader * wlanheader; 542 struct IeeeHeader * wlanheader;
473 struct RadiotapHeader * radioHeader; 543 struct RadiotapHeader * radioHeader;
474 struct GNUNET_MessageHeader * msgheader; 544 struct GNUNET_MessageHeader * msgheader;
545 struct FragmentationHeader fragheader;
475 uint16_t size = 0; 546 uint16_t size = 0;
547 const char * copystart = NULL;
548 uint16_t copysize = 0;
549 uint copyoffset = 0;
550 struct FragmentQueue * akt = NULL;
551 int exit = 0;
476 552
477 queue = plugin->pending_Sessions; 553 queue = plugin->pending_Sessions;
478 554
@@ -487,16 +563,99 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
487 563
488 //check if msg is valid to send 564 //check if msg is valid to send
489 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).value > 0){ 565 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).value > 0){
490 // fixme split msg if to large 566 // split msg if to large
491 567
492 //increment one, this is a new message 568 if (pm->message_size > WLAN_MTU) {
493 session->message_num_out ++; 569 size += sizeof(struct FragmentationHeader);
494 // fixme peer id is needed in each packet 570 // check for retransmission
495 size = pm->message_size + sizeof(struct RadiotapHeader) 571 if (GNUNET_TIME_absolute_get_duration(pm->last_ack).value > FRAGMENT_TIMEOUT) {
496 + sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader) 572 // TODO retransmit
497 + sizeof(struct FragmentationHeader); 573 // be positive and try again later :-D
574 pm->last_ack = GNUNET_TIME_absolute_get();
575 // find first missing fragment
576 exit = 0;
577 akt = pm->head;
578 pm->message_pos = 0;
579
580 //test if ack was already received
581 if (akt != NULL) {
582 while (exit == 0){
583 //if fragment is present, take next
584 if (akt->fragment_num == pm->message_pos) {
585 pm->message_pos ++;
586 }
587 //next ack is bigger then the fragment number
588 //in case there is something like this: (acks) 1, 2, 5, 6, ...
589 //and we send 3 again, the next number should be 4
590 if (akt->fragment_num > pm->message_pos) {
591 exit = 1;
592 }
593
594 akt = akt->next;
595 //test if this was the last ack
596 if (akt == NULL){
597 exit = 1;
598 }
599
600 }
601 }
602
603 }
604
605 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * pm->message_pos;
606 fragheader.fragment_off_or_num = pm->message_pos;
607 fragheader.message_id = session->message_id_out;
608
609 // start should be smaller then the packet size
610 //TODO send some other data if everything was send but not all acks are present
611 GNUNET_assert(copyoffset < pm->message_size);
612 copystart = pm->msg + copyoffset;
613
614 //size of the fragment is either the MTU - overhead
615 //or the missing part of the message in case this is the last fragment
616 copysize = GNUNET_MIN(pm->message_size - copyoffset,
617 WLAN_MTU - sizeof(struct FragmentationHeader));
618 fragheader.header.size = copysize;
619 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
620
621 //get the next missing fragment
622 exit = 0;
623 akt = pm->head;
624 pm->message_pos ++;
625
626 //test if ack was already received
627 if (akt != NULL) {
628 while (exit == 0){
629 //if fragment is present, take next
630 if (akt->fragment_num == pm->message_pos) {
631 pm->message_pos ++;
632 }
633 //next ack is bigger then the fragment number
634 //in case there is something like this: (acks) 1, 2, 5, 6, ...
635 //and we send 3 again, the next number should be 4
636 if (akt->fragment_num > pm->message_pos) {
637 exit = 1;
638 }
639
640 akt = akt->next;
641 //test if this was the last ack
642 if (akt == NULL){
643 exit = 1;
644 }
645
646 }
647 }
648
649 } else {
650 // there is no need to split
651 copystart = pm->msg;
652 copysize = pm->message_size;
653 }
654 size += copysize;
655 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
656 + sizeof(struct GNUNET_MessageHeader);
498 msgheader = GNUNET_malloc(size); 657 msgheader = GNUNET_malloc(size);
499 msgheader->size = pm->message_size + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader); 658 msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
500 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA; 659 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
501 660
502 radioHeader = (struct RadiotapHeader*) &msgheader[1]; 661 radioHeader = (struct RadiotapHeader*) &msgheader[1];
@@ -505,9 +664,23 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
505 wlanheader = (struct IeeeHeader *) &radioHeader[1]; 664 wlanheader = (struct IeeeHeader *) &radioHeader[1];
506 getWlanHeader(wlanheader); 665 getWlanHeader(wlanheader);
507 666
667
668 //could be faster if content is just send and not copyed before
669 //fragmentheader is needed
670 if (pm->message_size > WLAN_MTU){
671 fragheader.message_crc = getcrc16(copystart, copysize);
672 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
673 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
674 } else {
675 memcpy(&wlanheader[1],copystart,copysize);
676 }
677
508 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size); 678 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
679
680
509 } else { 681 } else {
510 //remove message 682 //remove message
683 //TODO free the queues (acks)
511 GNUNET_CONTAINER_DLL_remove (session->pending_messages_head, 684 GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
512 session->pending_messages_tail, 685 session->pending_messages_tail,
513 pm); 686 pm);
@@ -531,6 +704,8 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
531 704
532} 705}
533 706
707
708
534/** 709/**
535 * If we have pending messages, ask the server to 710 * If we have pending messages, ask the server to
536 * transmit them (schedule the respective tasks, etc.) 711 * transmit them (schedule the respective tasks, etc.)
@@ -564,6 +739,37 @@ process_pending_messages (struct Plugin * plugin)
564} 739}
565 740
566 741
742/**
743 * 32bit CRC
744 *
745 * @param msgbuf pointer tor the data
746 * @param msgbuf_size size of the data
747 *
748 * @return 32bit crc value
749 */
750
751uint32_t
752getcrc32 (const char *msgbuf,
753 size_t msgbuf_size){
754 //TODO calc some crc
755 return 0;
756}
757
758/**
759 * 16bit CRC
760 *
761 * @param msgbuf pointer tor the data
762 * @param msgbuf_size size of the data
763 *
764 * @return 16bit crc value
765 */
766
767uint16_t
768getcrc16 (const char *msgbuf,
769 size_t msgbuf_size){
770 //TODO calc some crc
771 return 0;
772}
567 773
568/** 774/**
569 * Function that can be used by the transport service to transmit 775 * Function that can be used by the transport service to transmit
@@ -607,7 +813,7 @@ wlan_plugin_send (void *cls,
607{ 813{
608 struct Plugin * plugin = cls; 814 struct Plugin * plugin = cls;
609 struct PendingMessage * newmsg = NULL; 815 struct PendingMessage * newmsg = NULL;
610 816 struct WlanHeader * wlanheader = NULL;
611 //check if msglen > 0 817 //check if msglen > 0
612 GNUNET_assert(msgbuf_size > 0); 818 GNUNET_assert(msgbuf_size > 0);
613 819
@@ -631,15 +837,20 @@ wlan_plugin_send (void *cls,
631 queue_Session(plugin, session); 837 queue_Session(plugin, session);
632 838
633 //queue message in session 839 //queue message in session
634 newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size); 840 newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size + sizeof(struct WlanHeader));
635 newmsg->msg = (const char*) &newmsg[1]; 841 newmsg->msg = (const char*) &newmsg[1];
636 //copy msg to buffer, not fragmented / segmented yet 842 wlanheader = (struct WlanHeader *) &newmsg[1];
637 memcpy(&newmsg[1], msgbuf, msgbuf_size); 843 //copy msg to buffer, not fragmented / segmented yet, but with message header
844 wlanheader->header.size = msgbuf_size;
845 wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
846 wlanheader->target = *target;
847 wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
848 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
638 newmsg->transmit_cont = cont; 849 newmsg->transmit_cont = cont;
639 newmsg->transmit_cont_cls = cont_cls; 850 newmsg->transmit_cont_cls = cont_cls;
640 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout); 851 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
641 newmsg->message_pos = 0; 852 newmsg->message_pos = 0;
642 newmsg->message_size = msgbuf_size; 853 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
643 newmsg->next = NULL; 854 newmsg->next = NULL;
644 855
645 //check if queue is empty 856 //check if queue is empty
@@ -688,7 +899,7 @@ wlan_plugin_disconnect (void *cls,
688 const struct GNUNET_PeerIdentity *target) 899 const struct GNUNET_PeerIdentity *target)
689{ 900{
690 // struct Plugin *plugin = cls; 901 // struct Plugin *plugin = cls;
691 // FIXME 902 // FIXME make something usefull :-D
692} 903}
693 904
694 905
@@ -812,10 +1023,12 @@ wlan_plugin_address_to_string (void *cls,
812} 1023}
813 1024
814 1025
815#if 1 1026
816/** 1027/**
817 * Function used for to process the data from the suid process 1028 * Function used for to process the data from the suid process
818 */ 1029 */
1030//TODO doxigen
1031
819static void 1032static void
820wlan_process_helper (void *cls, 1033wlan_process_helper (void *cls,
821 void *client, 1034 void *client,
@@ -829,6 +1042,8 @@ wlan_process_helper (void *cls,
829 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){ 1042 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
830 //TODO Control 1043 //TODO Control
831 if (hdr->size == 6){ 1044 if (hdr->size == 6){
1045 plugin->mac_address = GNUNET_malloc(6);
1046 memcpy(plugin->mac_address, &hdr[1],6);
832 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size)); 1047 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
833 plugin->env->notify_address (plugin->env->cls, 1048 plugin->env->notify_address (plugin->env->cls,
834 "wlan", 1049 "wlan",
@@ -922,9 +1137,6 @@ wlan_transport_start_wlan_helper (struct Plugin *plugin)
922 1137
923 1138
924 1139
925#endif
926
927
928/** 1140/**
929 * Entry point for the plugin. 1141 * Entry point for the plugin.
930 * 1142 *
@@ -966,6 +1178,8 @@ gnunet_plugin_transport_wlan_init (void *cls)
966 api->check_address = &wlan_plugin_address_suggested; 1178 api->check_address = &wlan_plugin_address_suggested;
967 api->address_to_string = &wlan_plugin_address_to_string; 1179 api->address_to_string = &wlan_plugin_address_to_string;
968 1180
1181 start_next_message_id();
1182
969 return api; 1183 return api;
970} 1184}
971 1185
@@ -973,6 +1187,7 @@ gnunet_plugin_transport_wlan_init (void *cls)
973/** 1187/**
974 * Exit point from the plugin. 1188 * Exit point from the plugin.
975 */ 1189 */
1190//TODO doxigen
976void * 1191void *
977gnunet_plugin_transport_wlan_done (void *cls) 1192gnunet_plugin_transport_wlan_done (void *cls)
978{ 1193{
@@ -981,6 +1196,7 @@ gnunet_plugin_transport_wlan_done (void *cls)
981 1196
982 GNUNET_assert(cls !=NULL); 1197 GNUNET_assert(cls !=NULL);
983 1198
1199 GNUNET_free_non_null(plugin->mac_address);
984 GNUNET_free (plugin); 1200 GNUNET_free (plugin);
985 GNUNET_free (api); 1201 GNUNET_free (api);
986 return NULL; 1202 return NULL;