2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/plugin_transport_wlan.c
23 * @brief transport plugin for wlan
24 * @author David Brodski
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
38 #define PROTOCOL_PREFIX "wlan"
41 * Max size of packet from helper
46 * Time until retransmission of a fragment in ms
48 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
50 #define FRAGMENT_QUEUE_SIZE 10
52 #define DEBUG_wlan GNUNET_YES
54 #define MESSAGE_LENGHT_UNKNOWN -1
55 #define NO_MESSAGE_OR_MESSAGE_FINISHED -2
59 * After how long do we expire an address that we
60 * learned from another peer if it is not reconfirmed
63 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
66 * Initial handshake message for a session.
71 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
73 struct GNUNET_MessageHeader header;
76 * Identit*mac_y of the node connecting (TCP client)
78 struct GNUNET_PeerIdentity clientIdentity;
84 * Encapsulation of all of the state of the plugin.
91 struct GNUNET_TRANSPORT_PluginEnvironment *env;
94 * List of open sessions. head
96 struct Sessionqueue *sessions;
99 * List of open sessions. tail
101 struct Sessionqueue *sessions_tail;
110 * encapsulation to the local wlan server prog
113 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
117 * stdout pipe handle for the gnunet-wlan-helper process
119 struct GNUNET_DISK_PipeHandle *server_stdout;
122 * stdout file handle for the gnunet-wlan-helper process
124 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
127 * stdin pipe handle for the gnunet-wlan-helper process
129 struct GNUNET_DISK_PipeHandle *server_stdin;
132 * stdin file handle for the gnunet-wlan-helper process
134 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
137 * ID of the gnunet-wlan-server std read task
139 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
142 * ID of the gnunet-wlan-server std read task
144 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
147 * ID of the delay task for writing
149 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
152 * The process id of the wlan process
154 struct GNUNET_OS_Process *server_proc;
157 * The interface of the wlan card given to us by the user.
162 * The mac_address of the wlan card given to us by the helper.
164 struct MacAddress mac_address;
167 * Sessions currently pending for transmission
168 * to this peer, if any.
170 struct Sessionqueue * pending_Sessions;
173 * Sessions currently pending for transmission
174 * to this peer (tail), if any.
176 struct Sessionqueue * pending_Sessions_tail;
179 * number of pending sessions
181 unsigned int pendingsessions;
184 * Messages in the fragmentation queue, head
187 struct FragmentMessage * pending_Fragment_Messages_head;
190 * Messages in the fragmentation queue, tail
193 struct FragmentMessage * pending_Fragment_Messages_tail;
196 * number of pending fragment message
199 unsigned int pending_fragment_messages;
202 * time of the next "hello-beacon"
205 struct GNUNET_TIME_Absolute beacon_time;
210 * Queue of sessions, for the general session queue and the pending session queue
215 struct Sessionqueue * next;
216 struct Sessionqueue * prev;
217 struct Session * content;
221 * Queue of ack received for messages send
226 struct AckQueue * next;
227 struct AckQueue * prev;
228 int fragment_num; //TODO change it to offset if better
234 * Queue for the fragments received
239 struct RecQueue * next;
240 struct RecQueue * prev;
247 * Information kept for each message that is yet to
250 struct PendingMessage
254 * The pending message
259 * Continuation function to call once the message
260 * has been sent. Can be NULL if there is no
261 * continuation to call.
263 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
266 * Cls for transmit_cont
268 void * transmit_cont_cls;
271 * Timeout value for the pending message.
273 struct GNUNET_TIME_Absolute timeout;
276 * Size of the message
283 * Session infos gathered from a messages
289 * the session this message belongs to
291 struct Session * session;
299 * Session handle for connections.
307 struct SessionHeader header;
310 * Pointer to the global plugin struct.
312 struct Plugin *plugin;
315 * Message currently pending for transmission
316 * to this peer, if any.
318 struct PendingMessage *pending_message;
321 * To whom are we talking to (set to our identity
322 * if we are still waiting for the welcome message)
324 struct GNUNET_PeerIdentity target;
327 * encapsulation of the receive data
329 //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
332 * offset of the next fragment for the receive_token, -1 means last message finished
338 * size of the message received,
339 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
340 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
346 * Sorted queue with the fragments received; head
349 struct RecQueue * frag_head;
352 * Sorted queue with the fragments received; tail
355 struct RecQueue * frag_tail;
363 * Address of the other peer (either based on our 'connect'
364 * call or on our 'accept' call).
369 * Last activity on this connection. Used to select preferred
372 struct GNUNET_TIME_Absolute last_activity;
375 * current number for message incoming, to distinguish between the messages
377 uint32_t message_id_in;
380 * current number for message outgoing, to distinguish between the messages
382 uint32_t message_id_out;
385 * does this session have a message in the fragment queue
395 struct FragmentMessage
398 * Session this message belongs to
401 struct Session *session;
404 * This is a doubly-linked list.
406 struct FragmentMessage *next;
409 * This is a doubly-linked list.
411 struct FragmentMessage *prev;
414 * The pending message
419 * Timeout value for the pending message.
421 struct GNUNET_TIME_Absolute timeout;
424 * Timeout value for the pending fragments.
425 * Stores the time when the next msg fragment ack has to be received
427 struct GNUNET_TIME_Absolute next_ack;
430 * Sorted queue with the acks received for fragments; head
433 struct AckQueue * head;
436 * Sorted queue with the acks received for fragments; tail
439 struct AckQueue * tail;
442 * Size of the message
447 * pos / next fragment number in the message, for fragmentation/segmentation,
448 * some acks can be missing but there is still time
450 uint32_t message_pos;
455 * Header for messages which need fragmentation
460 struct GNUNET_MessageHeader header;
463 * checksum/error correction
465 uint32_t crc GNUNET_PACKED;
468 * To whom are we talking to (set to our identity
469 * if we are still waiting for the welcome message)
471 struct GNUNET_PeerIdentity target;
473 // followed by payload
478 * Header for messages which need fragmentation
480 struct FragmentationHeader
483 struct GNUNET_MessageHeader header;
486 * To whom are we talking to (set to our identity
487 * if we are still waiting for the welcome message)
489 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
492 * ID of message, to distinguish between the messages, picked randomly.
494 uint32_t message_id GNUNET_PACKED;
497 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
499 uint16_t fragment_off_or_num GNUNET_PACKED;
502 * CRC of fragment (for error checking)
504 uint16_t message_crc GNUNET_PACKED;
508 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
509 * // 0x2 has data (not only ack)
510 * // 0x4 last fragment of message
513 // uint32_t flags GNUNET_PACKED;
516 * checksum/error correction
518 // uint32_t crc GNUNET_PACKED;
520 // followed by payload unless ACK
524 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
527 getRadiotapHeader(struct RadiotapHeader * Header);
530 getWlanHeader(struct IeeeHeader * Header);
533 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
536 getcrc16(const char *msgbuf, size_t msgbuf_size);
539 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
542 check_fragment_queue(struct Plugin * plugin);
545 getcrc32(const char *msgbuf, size_t msgbuf_size);
548 free_rec_frag_queue(struct Session * session);
551 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr);
554 wlan_process_helper (void *cls,
556 const struct GNUNET_MessageHeader *hdr);
559 * get the next message number, at the moment just a random one
564 get_next_message_id()
566 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
570 * start next message number generator
574 start_next_message_id()
576 //GNUNET_CRYPTO_random_init;
580 * search for a session with the addr
582 * @param plugin pointer to the plugin struct
583 * @param addr pointer to the mac address of the peer
584 * @return returns the session
587 static struct Session *
588 search_session(struct Plugin *plugin, const uint8_t * addr)
590 struct Sessionqueue * queue = plugin->sessions;
591 struct Sessionqueue * lastitem = NULL;
593 //just look at all the session for the needed one
594 while (queue != NULL)
596 // content is never NULL
597 GNUNET_assert (queue->content != NULL);
598 char * addr2 = queue->content->addr;
599 if (memcmp(addr, addr2, 6) == 0)
602 return queue->content;
612 * create a new session
614 * @param plugin pointer to the plugin struct
615 * @param addr pointer to the mac address of the peer
616 * @return returns the session
619 static struct Session *
620 create_session(struct Plugin *plugin,const uint8_t * addr)
622 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
624 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
626 queue->content = GNUNET_malloc (sizeof (struct Session));
627 queue->content->plugin = plugin;
628 memcpy(queue->content->addr, addr, 6);
629 queue->content->message_id_out = get_next_message_id();
630 queue->content->has_fragment = 0;
631 queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
633 plugin->session_count++;
634 return queue->content;
638 * get Session from address, create if no session exists
640 * @param plugin pointer to the plugin struct
641 * @param addr pointer to the mac address of the peer
642 * @return returns the session
644 //TODO add other possibilities to find the right session (are there other?)
645 static struct Session *
646 get_Session(struct Plugin *plugin, const uint8_t * addr)
648 struct Session * session = search_session(plugin, addr);
654 return create_session(plugin, addr);
656 /* -- not needed, layer above already has it--
657 //queue welcome message for new sessions, not realy needed
658 //struct WelcomeMessage welcome;
659 struct PendingMessage *pm;
660 pm = GNUNET_malloc (sizeof (struct PendingMessage));
661 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
662 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
663 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
664 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
665 //welcome.clientIdentity = *plugin->env->my_identity;
666 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
667 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
668 queue->content->pending_message = pm;
669 plugin->pendingsessions ++;
670 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
672 check_fragment_queue(plugin);
677 * Queue the session to send data
681 queue_Session (struct Plugin *plugin,
682 struct Session * session)
684 struct Sessionqueue * queue = plugin->pending_Sessions;
685 struct Sessionqueue * lastitem = NULL;
687 while (queue != NULL){
688 // content is never NULL
689 GNUNET_assert (queue->content == NULL);
690 // is session already in queue?
691 if (session == queue->content){
699 // Session is not in the queue
701 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
702 queue->content = session;
705 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
706 plugin->pending_Sessions_tail,
707 plugin->pending_Sessions_tail, queue);
708 plugin->pendingsessions ++;
714 free_acks (struct FragmentMessage * fm){
715 struct AckQueue * fq;
716 while (fm->head != NULL){
718 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
728 * Function to schedule the write task, executed after a delay
731 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
733 struct Plugin * plugin = cls;
734 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
736 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
739 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
740 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
742 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
743 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
744 &do_transmit, plugin);
750 * Function to calculate the time of the next periodic "hello-beacon"
753 set_next_beacon_time(struct Plugin * const plugin)
755 //under 10 known peers: once a second
756 if (plugin->session_count < 10)
758 plugin->beacon_time = GNUNET_TIME_absolute_add(
759 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
761 //under 30 known peers: every 10 seconds
762 else if (plugin->session_count < 30)
764 plugin->beacon_time = GNUNET_TIME_absolute_add(
765 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
766 GNUNET_TIME_UNIT_SECONDS, 10));
768 //over 30 known peers: once a minute
771 plugin->beacon_time = GNUNET_TIME_absolute_add(
772 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
778 struct GNUNET_TIME_Relative
779 get_next_frag_timeout(struct FragmentMessage * fm)
781 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
782 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
787 * Function to get the timeout value for acks for this session
790 struct GNUNET_TIME_Relative
791 get_ack_timeout (struct FragmentMessage * fm){
792 return FRAGMENT_TIMEOUT;
797 * Function to set the timer for the next timeout of the fragment queue
800 check_next_fragment_timeout(struct Plugin * const plugin)
802 struct FragmentMessage * fm;
803 struct GNUNET_TIME_Relative next_send;
805 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
808 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
810 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
812 fm = plugin->pending_Fragment_Messages_head;
814 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
816 //check if there are some fragments in the queue
820 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
822 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
823 &delay_fragment_task, plugin);
830 * Function to get the next queued Session, removes the session from the queue
833 static struct Session *
834 get_next_queue_Session (struct Plugin * plugin){
835 struct Session * session;
836 struct Sessionqueue * sessionqueue;
837 struct Sessionqueue * sessionqueue_alt;
838 struct PendingMessage * pm;
839 sessionqueue = plugin->pending_Sessions;
840 while (sessionqueue != NULL){
841 session = sessionqueue->content;
842 pm = session->pending_message;
844 //check for message timeout
845 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
846 //check if session has no message in the fragment queue
847 if (! session->has_fragment){
848 plugin->pendingsessions --;
849 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
850 plugin->pending_Sessions_tail, sessionqueue);
851 GNUNET_free(sessionqueue);
855 sessionqueue = sessionqueue->next;
859 session->pending_message = NULL;
860 //call the cont func that it did not work
861 if (pm->transmit_cont != NULL)
862 pm->transmit_cont (pm->transmit_cont_cls,
863 &(session->target), GNUNET_SYSERR);
864 GNUNET_free(pm->msg);
867 sessionqueue_alt = sessionqueue;
868 sessionqueue = sessionqueue->next;
869 plugin->pendingsessions --;
870 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
871 plugin->pending_Sessions_tail, sessionqueue_alt);
873 GNUNET_free(sessionqueue_alt);
884 * Function to sort the message into the message fragment queue
887 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
888 struct FragmentMessage * fm2;
889 //sort into the list at the right position
891 fm2 = plugin->pending_Fragment_Messages_head;
894 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
901 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
902 plugin->pending_Fragment_Messages_tail,fm2,fm);
907 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
912 GNUNET_free_non_null(fm->msg);
913 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
914 plugin->pending_Fragment_Messages_tail, fm);
916 plugin->pending_fragment_messages --;
917 check_fragment_queue(plugin);
923 * Function to check if there is some space in the fragment queue
927 check_fragment_queue (struct Plugin * plugin){
928 struct Session * session;
929 struct FragmentMessage * fm;
931 struct PendingMessage * pm;
933 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
934 session = get_next_queue_Session(plugin);
935 if (session != NULL){
936 pm = session->pending_message;
937 session->pending_message = NULL;
938 session->has_fragment = 1;
939 GNUNET_assert(pm != NULL);
941 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
942 fm->message_size = pm->message_size;
944 fm->session = session;
945 fm->timeout.abs_value = pm->timeout.abs_value;
947 fm->next_ack = GNUNET_TIME_absolute_get();
949 if (pm->transmit_cont != NULL)
950 pm->transmit_cont (pm->transmit_cont_cls,
951 &(session->target), GNUNET_OK);
954 sort_fragment_into_queue(plugin,fm);
955 plugin->pending_fragment_messages ++;
957 //generate new message id
958 session->message_id_out = get_next_message_id();
960 //check if timeout changed
961 check_next_fragment_timeout(plugin);
968 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
969 struct AckQueue * ack;
972 if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
973 * fm->tail->fragment_num)
977 //check if all acks are present
980 if (counter == ack->fragment_num)
989 fm->session->has_fragment = 0;
990 free_fragment_message(plugin, fm);
997 * Function called to when wlan helper is ready to get some data
1000 * @param tc GNUNET_SCHEDULER_TaskContext
1004 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1007 struct Plugin * plugin = cls;
1008 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1012 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1015 struct Session * session = NULL;
1016 struct FragmentMessage * fm = NULL;
1017 struct IeeeHeader * ieeewlanheader = NULL;
1018 struct RadiotapHeader * radioHeader = NULL;
1019 struct GNUNET_MessageHeader * msgheader = NULL;
1020 struct GNUNET_MessageHeader * msgheader2 = NULL;
1021 struct FragmentationHeader fragheader;
1022 struct FragmentationHeader * fragheaderptr = NULL;
1024 const char * copystart = NULL;
1025 uint16_t copysize = 0;
1026 uint copyoffset = 0;
1027 struct AckQueue * akt = NULL;
1029 //test if a "hello-beacon" has to be send
1030 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1032 //check if the message is not to big
1033 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1034 *(plugin->env->our_hello)) <= WLAN_MTU);
1035 size = sizeof(struct GNUNET_MessageHeader)
1036 + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1037 + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1038 *(plugin->env->our_hello));
1040 msgheader = GNUNET_malloc(size);
1041 msgheader->size = htons(size);
1042 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1044 radioHeader = (struct RadiotapHeader *) &msgheader[1];
1045 getRadiotapHeader(radioHeader);
1047 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1048 getWlanHeader(ieeewlanheader);
1050 msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1051 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello)) + sizeof(struct GNUNET_MessageHeader));
1052 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1054 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1055 *(plugin->env->our_hello)));
1058 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1060 GNUNET_assert(bytes == size);
1062 set_next_beacon_time(plugin);
1063 check_next_fragment_timeout(plugin);
1069 fm = plugin->pending_Fragment_Messages_head;
1070 GNUNET_assert(fm != NULL);
1071 session = fm->session;
1072 GNUNET_assert(session != NULL);
1074 // test if message timed out
1075 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
1077 GNUNET_assert(plugin->pending_fragment_messages > 0);
1078 plugin->pending_fragment_messages --;
1079 GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1080 plugin->pending_Fragment_Messages_tail, fm);
1082 GNUNET_free(fm->msg);
1085 check_fragment_queue(plugin);
1088 if (fm->message_size > WLAN_MTU) {
1089 size += sizeof(struct FragmentationHeader);
1090 // check/set for retransmission
1091 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
1093 // be positive and try again later :-D
1094 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1095 // find first missing fragment
1097 fm->message_pos = 0;
1099 //test if ack 0 was already received
1100 while (akt != NULL){
1101 //if fragment is present, take next
1102 if (akt->fragment_num == fm->message_pos) {
1105 //next ack is bigger then the fragment number
1106 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1107 //and we send 3 again, the next number should be 4
1108 else if (akt->fragment_num > fm->message_pos) {
1119 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
1120 fragheader.fragment_off_or_num = htons(fm->message_pos);
1121 fragheader.message_id = htonl(session->message_id_out);
1123 // start should be smaller then the packet size
1124 GNUNET_assert(copyoffset < fm->message_size);
1125 copystart = fm->msg + copyoffset;
1127 //size of the fragment is either the MTU - overhead
1128 //or the missing part of the message in case this is the last fragment
1129 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1130 WLAN_MTU - sizeof(struct FragmentationHeader));
1131 fragheader.header.size = htons(copysize + sizeof(struct FragmentationHeader));
1132 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1135 //get the next missing fragment
1139 //test if ack was already received
1140 while (akt != NULL){
1141 //if fragment is present, take next
1142 if (akt->fragment_num == fm->message_pos) {
1145 //next ack is bigger then the fragment number
1146 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1147 //and we send 3 again, the next number should be 4
1148 else if (akt->fragment_num > fm->message_pos) {
1155 // there is no need to split
1156 copystart = fm->msg;
1157 copysize = fm->message_size;
1161 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1162 + sizeof(struct GNUNET_MessageHeader);
1163 msgheader = GNUNET_malloc(size);
1164 msgheader->size = htons(size);
1165 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1167 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1168 getRadiotapHeader(radioHeader);
1170 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1171 getWlanHeader(ieeewlanheader);
1174 //could be faster if content is just send and not copyed before
1175 //fragmentheader is needed
1176 if (fm->message_size > WLAN_MTU){
1177 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1178 memcpy(&ieeewlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
1179 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1180 memcpy(&fragheaderptr[1],copystart,copysize);
1182 memcpy(&ieeewlanheader[1],copystart,copysize);
1185 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1186 GNUNET_assert(bytes == size);
1188 //check if this was the last fragment of this message, if true then queue at the end of the list
1189 if (copysize + copyoffset >= fm->message_size){
1190 GNUNET_assert(copysize + copyoffset == fm->message_size);
1192 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1193 plugin->pending_Fragment_Messages_tail, fm);
1195 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1196 plugin->pending_Fragment_Messages_tail, fm);
1197 // if fragments have opimized timeouts
1198 //sort_fragment_into_queue(plugin,fm);
1201 check_next_fragment_timeout(plugin);
1210 * @param msgbuf pointer tor the data
1211 * @param msgbuf_size size of the data
1213 * @return 32bit crc value
1217 getcrc32 (const char *msgbuf,
1218 size_t msgbuf_size){
1219 //TODO calc some crc
1226 * @param msgbuf pointer tor the data
1227 * @param msgbuf_size size of the data
1229 * @return 16bit crc value
1233 getcrc16 (const char *msgbuf,
1234 size_t msgbuf_size){
1235 //TODO calc some crc
1240 * Function that can be used by the transport service to transmit
1241 * a message using the plugin.
1243 * @param cls closure
1244 * @param target who should receive this message
1245 * @param priority how important is the message
1246 * @param msgbuf the message to transmit
1247 * @param msgbuf_size number of bytes in 'msgbuf'
1248 * @param timeout when should we time out
1249 * @param session which session must be used (or NULL for "any")
1250 * @param addr the address to use (can be NULL if the plugin
1251 * is "on its own" (i.e. re-use existing TCP connection))
1252 * @param addrlen length of the address in bytes
1253 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1254 * otherwise the plugin may use other addresses or
1255 * existing connections (if available)
1256 * @param cont continuation to call once the message has
1257 * been transmitted (or if the transport is ready
1258 * for the next transmission call; or if the
1259 * peer disconnected...)
1260 * @param cont_cls closure for cont
1261 * @return number of bytes used (on the physical network, with overheads);
1262 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1263 * and does NOT mean that the message was not transmitted (DV)
1266 wlan_plugin_send (void *cls,
1267 const struct GNUNET_PeerIdentity * target,
1270 unsigned int priority,
1271 struct GNUNET_TIME_Relative timeout,
1272 struct Session *session,
1276 GNUNET_TRANSPORT_TransmitContinuation cont,
1279 struct Plugin * plugin = cls;
1280 struct PendingMessage * newmsg = NULL;
1281 struct WlanHeader * wlanheader = NULL;
1282 //check if msglen > 0
1283 GNUNET_assert(msgbuf_size > 0);
1285 //get session if needed
1286 if (session == NULL)
1288 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1290 session = get_Session(plugin, addr);
1294 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1295 _("Wlan Address len %d is wrong\n"), addrlen);
1300 //TODO target "problem" not solved
1301 session->target = *target;
1304 //first queue session
1305 queue_Session(plugin, session);
1307 //queue message in session
1308 //test if there is no other message in the "queue"
1309 GNUNET_assert (session->pending_message == NULL);
1311 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1312 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1313 wlanheader = (struct WlanHeader *) newmsg->msg;
1314 //copy msg to buffer, not fragmented / segmented yet, but with message header
1315 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1316 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1317 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1318 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1319 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1320 newmsg->transmit_cont = cont;
1321 newmsg->transmit_cont_cls = cont_cls;
1322 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1323 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1325 session->pending_message = newmsg;
1327 check_fragment_queue(plugin);
1328 //FIXME not the correct size
1334 static struct FragmentMessage *
1335 get_fragment_message_from_session(struct Session * session)
1337 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1340 if (fm->session == session)
1350 * Function that can be used to force the plugin to disconnect
1351 * from the given peer and cancel all previous transmissions
1352 * (and their continuation).
1354 * @param cls closure
1355 * @param target peer from which to disconnect
1358 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1360 struct Plugin *plugin = cls;
1361 struct Sessionqueue * queue = plugin->sessions;
1362 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1363 struct PendingMessage * pm = NULL;
1364 struct FragmentMessage * fm;
1366 // just look at all the session for the needed one
1367 while (queue != NULL)
1369 // content is never NULL
1370 GNUNET_assert (queue->content != NULL);
1371 if (memcmp(target, &(queue->content->target),
1372 sizeof(struct GNUNET_PeerIdentity)) == 0)
1375 //is this session pending for send
1376 while (pendingsession != NULL)
1378 if (pendingsession->content == queue->content)
1380 plugin->pendingsessions --;
1381 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1382 plugin->pending_Sessions_tail, pendingsession);
1383 GNUNET_free(pendingsession);
1386 pendingsession = pendingsession->next;
1389 //is something of this session in the fragment queue?
1390 fm = get_fragment_message_from_session(queue->content);
1391 free_fragment_message(plugin,fm);
1393 //dispose all received fragments
1394 free_rec_frag_queue(queue->content);
1396 // remove PendingMessage
1397 pm = queue->content->pending_message;
1398 GNUNET_free(pm->msg);
1401 GNUNET_free(queue->content);
1402 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1404 plugin->session_count --;
1409 queue = queue->next;
1415 * Convert the transports address to a nice, human-readable
1418 * @param cls closure
1419 * @param type name of the transport that generated the address
1420 * @param addr one of the addresses of the host, NULL for the last address
1421 * the specific address format depends on the transport
1422 * @param addrlen length of the address
1423 * @param numeric should (IP) addresses be displayed in numeric form?
1424 * @param timeout after how long should we give up?
1425 * @param asc function to call on each string
1426 * @param asc_cls closure for asc
1429 wlan_plugin_address_pretty_printer (void *cls,
1434 struct GNUNET_TIME_Relative timeout,
1435 GNUNET_TRANSPORT_AddressStringCallback
1439 const unsigned char * input;
1441 GNUNET_assert(cls !=NULL);
1444 /* invalid address (MAC addresses have 6 bytes) */
1446 asc (asc_cls, NULL);
1449 input = (const unsigned char*) addr;
1450 GNUNET_snprintf (ret,
1452 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1454 input[0], input[1], input[2], input[3], input[4], input[5]);
1461 * Another peer has suggested an address for this
1462 * peer and transport plugin. Check that this could be a valid
1463 * address. If so, consider adding it to the list
1466 * @param cls closure
1467 * @param addr pointer to the address
1468 * @param addrlen length of addr
1469 * @return GNUNET_OK if this is a plausible address for this peer
1475 wlan_plugin_address_suggested (void *cls,
1479 //struct Plugin *plugin = cls;
1481 /* check if the address is plausible; if so,
1482 add it to our list! */
1484 GNUNET_assert(cls !=NULL);
1485 //FIXME mitm is not checked
1486 //Mac Adress has 6 bytes
1488 /* TODO check for bad addresses like milticast, broadcast, etc */
1491 return GNUNET_SYSERR;
1494 return GNUNET_SYSERR;
1499 * Function called for a quick conversion of the binary address to
1500 * a numeric address. Note that the caller must not free the
1501 * address and that the next call to this function is allowed
1502 * to override the address again.
1504 * @param cls closure
1505 * @param addr binary address
1506 * @param addrlen length of the address
1507 * @return string representing the same address
1510 wlan_plugin_address_to_string (void *cls,
1515 const unsigned char * input;
1517 GNUNET_assert(cls !=NULL);
1520 /* invalid address (MAC addresses have 6 bytes) */
1524 input = (const unsigned char*) addr;
1525 GNUNET_snprintf (ret,
1527 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1529 input[0], input[1], input[2], input[3], input[4], input[5]);
1530 return GNUNET_strdup (ret);
1534 * Function to test if fragment number already exists in the fragments received
1538 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1540 struct RecQueue * rec_queue = session->frag_head;
1541 while (rec_queue != NULL)
1543 if (rec_queue->num == fh->fragment_off_or_num)
1547 rec_queue = rec_queue->next;
1555 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1557 struct RecQueue * rec_queue2 = session->frag_head;
1558 struct WlanHeader * wlanheader = NULL;
1559 //first received fragment of message
1560 if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1562 session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1564 //this is the first fragment of the message (fragment id 0)
1565 if (rec_queue->num == 0)
1567 wlanheader = (struct WlanHeader *) rec_queue->msg;
1568 session->rec_size = wlanheader->header.size;
1572 while (rec_queue2 != NULL)
1574 if (rec_queue2->num > rec_queue->num)
1576 //next element number is grater than the current num
1577 GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1580 rec_queue = rec_queue->next;
1582 //no element has a grater number
1583 GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1587 * Function to dispose the fragments received for a message
1591 free_rec_frag_queue(struct Session * session)
1593 struct RecQueue * rec_queue = session->frag_head;
1594 struct RecQueue * rec_queue2;
1595 while (rec_queue != NULL)
1597 rec_queue2 = rec_queue;
1598 rec_queue = rec_queue->next;
1599 GNUNET_free(rec_queue2);
1601 session->frag_head = NULL;
1602 session->frag_tail = NULL;
1603 session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1607 * Function to check if all fragments of a message have been received
1611 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1612 struct RecQueue * rec_queue = session->frag_head;
1613 int packetsize = session->rec_size;
1617 //some fragment should be received
1618 GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1619 //check if first fragment is present
1620 if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1623 while (rec_queue != NULL){
1624 sum += rec_queue->size;
1625 //check if all fragment numbers are present
1626 if (rec_queue->num != aktnum){
1630 rec_queue = rec_queue->next;
1632 //sum should always be smaller or equal of
1633 GNUNET_assert(sum <= packetsize);
1634 if (sum == packetsize){
1635 //copy fragments together
1636 msg = GNUNET_malloc(packetsize);
1637 rec_queue = session->frag_head;
1639 while (rec_queue != NULL){
1640 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1641 aktnum += rec_queue->size;
1642 rec_queue = rec_queue->next;
1644 free_rec_frag_queue(session);
1645 //call wlan_process_helper to process the message
1646 wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1653 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr)
1655 struct Plugin *plugin = cls;
1656 struct Session * session = NULL;
1657 struct Session_light * session_light = NULL;
1659 struct WlanHeader * wlanheader = NULL;
1660 struct FragmentationHeader * fh = NULL;
1661 struct FragmentMessage * fm = NULL;
1663 const char * tempmsg = NULL;
1665 struct AckQueue * ack = NULL;
1666 struct AckQueue * ack2 = NULL;
1668 struct RecQueue * rec_queue = NULL;
1669 const struct GNUNET_MessageHeader * temp_hdr = NULL;
1671 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1673 //TODO better DOS protection, error handling
1674 GNUNET_assert(client != NULL);
1675 session_light = (struct Session_light *) client;
1676 if (session_light->session == NULL){
1677 session_light->session = get_Session(plugin, session_light->addr);
1679 GNUNET_assert(GNUNET_HELLO_get_id(
1680 (const struct GNUNET_HELLO_Message *) &hdr[1],
1681 &(session_light->session->target) ) != GNUNET_SYSERR);
1686 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1688 GNUNET_assert(client != NULL);
1689 session_light = (struct Session_light *) client;
1690 if (session_light->session == NULL){
1691 session_light->session = search_session(plugin, session_light->addr);
1693 session = session_light->session;
1694 wlanheader =(struct WlanHeader *) &hdr[1];
1695 tempmsg = (char*) &wlanheader[1];
1696 temp_hdr = ( const struct GNUNET_MessageHeader *) &wlanheader[1];
1698 if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc){
1699 //wrong crc, dispose message
1700 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1701 "WLAN message crc was wrong\n");
1705 //if not in session list
1706 if (session == NULL){
1708 //try if it is a hello message
1709 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO){
1710 session = create_session(plugin, session_light->addr);
1711 session_light->session = session;
1712 GNUNET_assert(GNUNET_HELLO_get_id(
1713 (const struct GNUNET_HELLO_Message *) temp_hdr,
1714 &session->target ) != GNUNET_SYSERR);
1717 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1718 "WLAN client not in session list and not a hello message\n");
1722 //"receive" the message
1723 struct GNUNET_TRANSPORT_ATS_Information distance[2];
1724 distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1725 distance[0].value = htonl (1);
1726 distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1727 distance[1].value = htonl (0);
1728 plugin->env->receive(plugin, &session->target,
1729 temp_hdr, (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1730 session, session->addr, sizeof(session->addr));
1733 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1735 GNUNET_assert(client != NULL);
1736 session_light = (struct Session_light *) client;
1737 if (session_light->session == NULL)
1739 session_light->session = search_session(plugin, session_light->addr);
1741 session = session_light->session;
1743 fh = (struct FragmentationHeader *) hdr;
1744 tempmsg = (char*) &fh[1];
1746 //if not in session list
1747 if (session != NULL)
1749 if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1751 //wrong crc, dispose message
1752 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1753 "WLAN fragment crc was wrong\n");
1758 //todo fragments do not timeout
1759 //check if message_id is rigth or it is a new msg
1760 if ((session->message_id_in == ntohs(fh->message_id))
1761 || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1763 session->message_id_in = ntohs(fh->message_id);
1764 if (is_double_msg(session, fh) != GNUNET_YES)
1766 rec_queue = GNUNET_malloc(sizeof (struct RecQueue) +
1767 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1768 rec_queue->size = ntohs(fh->header.size
1769 - sizeof(struct FragmentationHeader));
1770 rec_queue->num = ntohs(fh->fragment_off_or_num);
1771 rec_queue->msg = (char*) &rec_queue[1];
1772 //copy msg to buffer
1773 memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1774 insert_fragment_in_queue(session, rec_queue);
1775 check_rec_finished_msg(plugin, session_light, session);
1779 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1780 "WLAN fragment is a clone\n");
1786 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1787 "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
1794 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1795 "WLAN client not in session list and it is a fragment message\n");
1801 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1803 GNUNET_assert(client != NULL);
1804 session_light = (struct Session_light *) client;
1805 if (session_light->session == NULL)
1807 session_light->session = search_session(plugin, session_light->addr);
1808 GNUNET_assert(session_light->session != NULL);
1810 session = session_light->session;
1811 fh = (struct FragmentationHeader *) &hdr[1];
1812 if (fh->message_id == session->message_id_out)
1814 fm = get_fragment_message_from_session(session);
1821 if (ack2->fragment_num != fh->fragment_off_or_num)
1823 // check if next ack has bigger number
1824 if (ack2->fragment_num > fh->fragment_off_or_num)
1826 ack = GNUNET_malloc(sizeof(struct AckQueue));
1827 ack->fragment_num = fh->fragment_off_or_num;
1828 GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
1830 check_finished_fragment(plugin, fm);
1841 //GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
1842 //should never happen but...
1843 //check_finished_fragment(plugin, fm);
1847 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1848 "WLAN fragment not in fragment list but id is right\n");
1858 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN packet has not the right type\n");
1865 * Function used for to process the data from the suid process
1870 wlan_process_helper (void *cls,
1872 const struct GNUNET_MessageHeader *hdr)
1874 struct Plugin *plugin = cls;
1875 struct IeeeHeader * wlanIeeeHeader = NULL;
1876 struct Session_light * session_light = NULL;
1877 const struct GNUNET_MessageHeader * temp_hdr = NULL;
1882 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
1884 //call wlan_process_helper with the message inside, later with wlan: analyze signal
1885 GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
1886 wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
1888 session_light = GNUNET_malloc(sizeof(struct Session_light));
1889 memcpy(session_light->addr, &(wlanIeeeHeader->mac3), sizeof(struct MacAddress));
1890 session_light->session = search_session(plugin, session_light->addr);
1892 //process only if it is an broadcast or for this computer both with the gnunet bssid
1894 if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress)))
1896 //check for broadcast or mac
1897 if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac, sizeof(struct MacAddress))
1898 || memcmp(&(wlanIeeeHeader->mac1), &(plugin->mac_address),
1899 sizeof(struct MacAddress)))
1901 // process the inner data
1903 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
1904 while (pos < hdr->size)
1906 wlan_data_helper(plugin, &session_light, temp_hdr);
1907 pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
1913 GNUNET_free(session_light);
1919 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
1922 //TODO use struct wlan_helper_control
1923 if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
1925 //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
1926 memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
1928 GNUNET_ERROR_TYPE_DEBUG,
1929 "Notifying transport of address %s\n",
1930 wlan_plugin_address_to_string(cls, &(plugin->mac_address), hdr->size));
1931 plugin->env->notify_address(plugin->env->cls, "wlan",
1932 &plugin->mac_address, sizeof(struct MacAddress),
1933 GNUNET_TIME_UNIT_FOREVER_REL);
1937 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
1938 plugin->mac_address);
1947 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN helper packet has not the right type\n");
1954 wlan_plugin_helper_read (void *cls,
1955 const struct GNUNET_SCHEDULER_TaskContext *tc)
1957 struct Plugin *plugin = cls;
1958 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1960 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
1963 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1966 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1967 mybuf, sizeof(mybuf));
1971 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1972 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1976 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1977 mybuf, bytes, GNUNET_NO, GNUNET_NO);
1979 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1980 plugin->server_read_task =
1981 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1982 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1987 * Start the gnunet-wlan-helper process.
1989 * @param plugin the transport plugin
1990 * @param testmode should we use the dummy driver for testing?
1991 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1994 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
1996 const char * filename = "gnunet-transport-wlan-helper";
1997 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1998 if (plugin->server_stdout == NULL)
1999 return GNUNET_SYSERR;
2001 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2002 if (plugin->server_stdin == NULL)
2003 return GNUNET_SYSERR;
2006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2007 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename, plugin->interface, testmode);
2009 /* Start the server process */
2011 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2012 plugin->server_stdout, filename,filename, plugin->interface, ((testmode==1)?"1":"0"), NULL);
2013 if (plugin->server_proc == NULL)
2016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2017 "Failed to start gnunet-wlan-helper process\n");
2019 return GNUNET_SYSERR;
2021 /* Close the write end of the read pipe */
2022 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2024 /* Close the read end of the write pipe */
2025 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2027 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2028 GNUNET_DISK_PIPE_END_READ);
2029 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2030 GNUNET_DISK_PIPE_END_WRITE);
2032 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2033 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2034 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2035 &wlan_plugin_helper_read, plugin);
2041 * Exit point from the plugin.
2046 libgnunet_plugin_transport_wlan_done (void *cls)
2048 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2049 struct Plugin *plugin = api->cls;
2051 GNUNET_assert(cls !=NULL);
2053 if (plugin->consoltoken != NULL)
2054 GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2056 GNUNET_free_non_null(plugin->interface);
2057 GNUNET_free (plugin);
2063 * Entry point for the plugin.
2065 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2066 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2069 libgnunet_plugin_transport_wlan_init (void *cls)
2071 //struct GNUNET_SERVICE_Context *service;
2072 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2073 struct GNUNET_TRANSPORT_PluginFunctions *api;
2074 struct Plugin *plugin;
2077 GNUNET_assert(cls !=NULL);
2079 plugin = GNUNET_malloc (sizeof (struct Plugin));
2081 plugin->pendingsessions = 0;
2082 plugin->session_count = 0;
2083 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2084 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2085 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2087 testmode = GNUNET_NO;
2088 if (GNUNET_CONFIGURATION_have_value (env->cfg,
2089 "transport-wlan", "TESTMODE"))
2091 testmode = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2092 "transport-wlan","TESTMODE");
2095 if (GNUNET_CONFIGURATION_have_value (env->cfg,
2096 "transport-wlan", "INTERFACE"))
2098 if (GNUNET_CONFIGURATION_get_value_string (env->cfg,
2099 "transport-wlan","INTERFACE", &(plugin->interface)) != GNUNET_YES){
2100 libgnunet_plugin_transport_wlan_done(plugin);
2105 wlan_transport_start_wlan_helper(plugin, testmode);
2106 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2108 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2109 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2111 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2113 api->send = &wlan_plugin_send;
2114 api->disconnect = &wlan_plugin_disconnect;
2115 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2116 api->check_address = &wlan_plugin_address_suggested;
2117 api->address_to_string = &wlan_plugin_address_to_string;
2120 start_next_message_id();
2125 /* end of plugin_transport_wlan.c */