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_NO
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 * Identity of the node connecting (TCP client)
78 struct GNUNET_PeerIdentity clientIdentity;
83 * Encapsulation of all of the state of the plugin.
90 struct GNUNET_TRANSPORT_PluginEnvironment *env;
93 * List of open sessions. head
95 struct Sessionqueue *sessions;
98 * List of open sessions. tail
100 struct Sessionqueue *sessions_tail;
109 * encapsulation to the local wlan server prog
112 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
116 * stdout pipe handle for the gnunet-wlan-helper process
118 struct GNUNET_DISK_PipeHandle *server_stdout;
121 * stdout file handle for the gnunet-wlan-helper process
123 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
126 * stdin pipe handle for the gnunet-wlan-helper process
128 struct GNUNET_DISK_PipeHandle *server_stdin;
131 * stdin file handle for the gnunet-wlan-helper process
133 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
136 * ID of the gnunet-wlan-server std read task
138 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
141 * ID of the gnunet-wlan-server std read task
143 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
146 * ID of the delay task for writing
148 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
151 * The process id of the wlan process
153 struct GNUNET_OS_Process *server_proc;
156 * The interface of the wlan card given to us by the user.
161 * The mac_address of the wlan card given to us by the helper.
166 * Sessions currently pending for transmission
167 * to this peer, if any.
169 struct Sessionqueue * pending_Sessions;
172 * Sessions currently pending for transmission
173 * to this peer (tail), if any.
175 struct Sessionqueue * pending_Sessions_tail;
178 * number of pending sessions
180 unsigned int pendingsessions;
183 * Messages in the fragmentation queue, head
186 struct FragmentMessage * pending_Fragment_Messages_head;
189 * Messages in the fragmentation queue, tail
192 struct FragmentMessage * pending_Fragment_Messages_tail;
195 * number of pending fragment message
198 unsigned int pending_fragment_messages;
201 * time of the next "hello-beacon"
204 struct GNUNET_TIME_Absolute beacon_time;
209 * Queue of sessions, for the general session queue and the pending session queue
214 struct Sessionqueue * next;
215 struct Sessionqueue * prev;
216 struct Session * content;
220 * Queue of ack received for messages send
225 struct AckQueue * next;
226 struct AckQueue * prev;
227 int fragment_num; //TODO change it to offset if better
231 * Queue for the fragments received
236 struct RecQueue * next;
237 struct RecQueue * prev;
244 * Information kept for each message that is yet to
247 struct PendingMessage
251 * The pending message
256 * Continuation function to call once the message
257 * has been sent. Can be NULL if there is no
258 * continuation to call.
260 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
263 * Cls for transmit_cont
265 void * transmit_cont_cls;
268 * Timeout value for the pending message.
270 struct GNUNET_TIME_Absolute timeout;
273 * Size of the message
280 * Session infos gathered from a messages
286 * the session this message belongs to
288 struct Session * session;
296 * Session handle for connections.
304 struct SessionHeader header;
307 * Pointer to the global plugin struct.
309 struct Plugin *plugin;
312 * Message currently pending for transmission
313 * to this peer, if any.
315 struct PendingMessage *pending_message;
318 * To whom are we talking to (set to our identity
319 * if we are still waiting for the welcome message)
321 struct GNUNET_PeerIdentity target;
324 * encapsulation of the receive data
326 //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
329 * offset of the next fragment for the receive_token, -1 means last message finished
335 * size of the message received,
336 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
337 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
343 * Sorted queue with the fragments received; head
346 struct RecQueue * frag_head;
349 * Sorted queue with the fragments received; tail
352 struct RecQueue * frag_tail;
360 * Address of the other peer (either based on our 'connect'
361 * call or on our 'accept' call).
366 * Last activity on this connection. Used to select preferred
369 struct GNUNET_TIME_Absolute last_activity;
372 * current number for message incoming, to distinguish between the messages
374 uint32_t message_id_in;
377 * current number for message outgoing, to distinguish between the messages
379 uint32_t message_id_out;
382 * does this session have a message in the fragment queue
392 struct FragmentMessage
395 * Session this message belongs to
398 struct Session *session;
401 * This is a doubly-linked list.
403 struct FragmentMessage *next;
406 * This is a doubly-linked list.
408 struct FragmentMessage *prev;
411 * The pending message
416 * Timeout value for the pending message.
418 struct GNUNET_TIME_Absolute timeout;
421 * Timeout value for the pending fragments.
422 * Stores the time when the next msg fragment ack has to be received
424 struct GNUNET_TIME_Absolute next_ack;
427 * Sorted queue with the acks received for fragments; head
430 struct AckQueue * head;
433 * Sorted queue with the acks received for fragments; tail
436 struct AckQueue * tail;
439 * Size of the message
444 * pos / next fragment number in the message, for fragmentation/segmentation,
445 * some acks can be missing but there is still time
447 uint32_t message_pos;
452 * Header for messages which need fragmentation
457 struct GNUNET_MessageHeader header;
460 * checksum/error correction
462 uint32_t crc GNUNET_PACKED;
465 * To whom are we talking to (set to our identity
466 * if we are still waiting for the welcome message)
468 struct GNUNET_PeerIdentity target;
470 // followed by payload
475 * Header for messages which need fragmentation
477 struct FragmentationHeader
480 struct GNUNET_MessageHeader header;
483 * To whom are we talking to (set to our identity
484 * if we are still waiting for the welcome message)
486 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
489 * ID of message, to distinguish between the messages, picked randomly.
491 uint32_t message_id GNUNET_PACKED;
494 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
496 uint16_t fragment_off_or_num GNUNET_PACKED;
499 * CRC of fragment (for error checking)
501 uint16_t message_crc GNUNET_PACKED;
505 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
506 * // 0x2 has data (not only ack)
507 * // 0x4 last fragment of message
510 // uint32_t flags GNUNET_PACKED;
513 * checksum/error correction
515 // uint32_t crc GNUNET_PACKED;
517 // followed by payload unless ACK
521 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
524 getRadiotapHeader(struct RadiotapHeader * Header);
527 getWlanHeader(struct IeeeHeader * Header);
530 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
533 getcrc16(const char *msgbuf, size_t msgbuf_size);
536 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
539 check_fragment_queue(struct Plugin * plugin);
542 getcrc32(const char *msgbuf, size_t msgbuf_size);
545 free_rec_frag_queue(struct Session * session);
548 wlan_process_helper (void *cls,
550 const struct GNUNET_MessageHeader *hdr);
553 * get the next message number, at the moment just a random one
558 get_next_message_id()
560 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
564 * start next message number generator
568 start_next_message_id()
570 //GNUNET_CRYPTO_random_init;
574 * search for a session with the addr
576 * @param plugin pointer to the plugin struct
577 * @param addr pointer to the mac address of the peer
578 * @return returns the session
581 static struct Session *
582 search_session(struct Plugin *plugin, const uint8_t * addr)
584 struct Sessionqueue * queue = plugin->sessions;
585 struct Sessionqueue * lastitem = NULL;
587 //just look at all the session for the needed one
588 while (queue != NULL)
590 // content is never NULL
591 GNUNET_assert (queue->content == NULL);
592 char * addr2 = queue->content->addr;
593 if (memcmp(addr, addr2, 6) == 0)
596 return queue->content;
606 * create a new session
608 * @param plugin pointer to the plugin struct
609 * @param addr pointer to the mac address of the peer
610 * @return returns the session
613 static struct Session *
614 create_session(struct Plugin *plugin,const uint8_t * addr)
616 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
618 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
620 queue->content = GNUNET_malloc (sizeof (struct Session));
621 queue->content->plugin = plugin;
622 memcpy(queue->content->addr, addr, 6);
623 queue->content->message_id_out = get_next_message_id();
624 queue->content->has_fragment = 0;
625 queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
627 plugin->session_count++;
628 return queue->content;
632 * get Session from address, create if no session exists
634 * @param plugin pointer to the plugin struct
635 * @param addr pointer to the mac address of the peer
636 * @return returns the session
638 //TODO add other possibilities to find the right session (are there other?)
639 static struct Session *
640 get_Session(struct Plugin *plugin, const uint8_t * addr)
642 struct Session * session = search_session(plugin, addr);
648 return create_session(plugin, addr);
650 /* -- not needed, layer above already has it--
651 //queue welcome message for new sessions, not realy needed
652 //struct WelcomeMessage welcome;
653 struct PendingMessage *pm;
654 pm = GNUNET_malloc (sizeof (struct PendingMessage));
655 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
656 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
657 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
658 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
659 //welcome.clientIdentity = *plugin->env->my_identity;
660 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
661 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
662 queue->content->pending_message = pm;
663 plugin->pendingsessions ++;
664 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
666 check_fragment_queue(plugin);
671 * Queue the session to send data
675 queue_Session (struct Plugin *plugin,
676 struct Session * session)
678 struct Sessionqueue * queue = plugin->pending_Sessions;
679 struct Sessionqueue * lastitem = NULL;
681 while (queue != NULL){
682 // content is never NULL
683 GNUNET_assert (queue->content == NULL);
684 // is session already in queue?
685 if (session == queue->content){
693 // Session is not in the queue
695 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
696 queue->content = session;
699 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
700 plugin->pending_Sessions_tail,
701 plugin->pending_Sessions_tail, queue);
702 plugin->pendingsessions ++;
708 free_acks (struct FragmentMessage * fm){
709 struct AckQueue * fq;
710 while (fm->head != NULL){
712 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
722 * Function to schedule the write task, executed after a delay
725 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
727 struct Plugin * plugin = cls;
728 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
730 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
733 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
734 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
736 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
737 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
738 &do_transmit, plugin);
744 * Function to calculate the time of the next periodic "hello-beacon"
747 set_next_beacon_time(struct Plugin * const plugin)
749 //under 10 known peers: once a second
750 if (plugin->session_count < 10)
752 plugin->beacon_time = GNUNET_TIME_absolute_add(
753 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
755 //under 30 known peers: every 10 seconds
756 else if (plugin->session_count < 30)
758 plugin->beacon_time = GNUNET_TIME_absolute_add(
759 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
760 GNUNET_TIME_UNIT_SECONDS, 10));
762 //over 30 known peers: once a minute
765 plugin->beacon_time = GNUNET_TIME_absolute_add(
766 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
772 struct GNUNET_TIME_Relative
773 get_next_frag_timeout(struct FragmentMessage * fm)
775 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
776 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
781 * Function to get the timeout value for acks for this session
784 struct GNUNET_TIME_Relative
785 get_ack_timeout (struct FragmentMessage * fm){
786 return FRAGMENT_TIMEOUT;
791 * Function to set the timer for the next timeout of the fragment queue
794 check_next_fragment_timeout(struct Plugin * const plugin)
796 struct FragmentMessage * fm;
797 struct GNUNET_TIME_Relative next_send;
799 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
802 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
804 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
806 fm = plugin->pending_Fragment_Messages_head;
808 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
810 //check if there are some fragments in the queue
814 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
816 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
817 &delay_fragment_task, plugin);
824 * Function to get the next queued Session, removes the session from the queue
827 static struct Session *
828 get_next_queue_Session (struct Plugin * plugin){
829 struct Session * session;
830 struct Sessionqueue * sessionqueue;
831 struct Sessionqueue * sessionqueue_alt;
832 struct PendingMessage * pm;
833 sessionqueue = plugin->pending_Sessions;
834 while (sessionqueue != NULL){
835 session = sessionqueue->content;
836 pm = session->pending_message;
838 //check for message timeout
839 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
840 //check if session has no message in the fragment queue
841 if (! session->has_fragment){
842 plugin->pendingsessions --;
843 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
844 plugin->pending_Sessions_tail, sessionqueue);
845 GNUNET_free(sessionqueue);
849 sessionqueue = sessionqueue->next;
853 session->pending_message = NULL;
854 //call the cont func that it did not work
855 if (pm->transmit_cont != NULL)
856 pm->transmit_cont (pm->transmit_cont_cls,
857 &(session->target), GNUNET_SYSERR);
858 GNUNET_free(pm->msg);
861 sessionqueue_alt = sessionqueue;
862 sessionqueue = sessionqueue->next;
863 plugin->pendingsessions --;
864 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
865 plugin->pending_Sessions_tail, sessionqueue_alt);
867 GNUNET_free(sessionqueue_alt);
878 * Function to sort the message into the message fragment queue
881 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
882 struct FragmentMessage * fm2;
883 //sort into the list at the right position
885 fm2 = plugin->pending_Fragment_Messages_head;
888 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
895 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
896 plugin->pending_Fragment_Messages_tail,fm2,fm);
901 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
906 GNUNET_free_non_null(fm->msg);
907 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
908 plugin->pending_Fragment_Messages_tail, fm);
910 plugin->pending_fragment_messages --;
911 check_fragment_queue(plugin);
917 * Function to check if there is some space in the fragment queue
921 check_fragment_queue (struct Plugin * plugin){
922 struct Session * session;
923 struct FragmentMessage * fm;
925 struct PendingMessage * pm;
927 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
928 session = get_next_queue_Session(plugin);
929 if (session != NULL){
930 pm = session->pending_message;
931 session->pending_message = NULL;
932 session->has_fragment = 1;
933 GNUNET_assert(pm != NULL);
935 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
936 fm->message_size = pm->message_size;
938 fm->session = session;
939 fm->timeout.abs_value = pm->timeout.abs_value;
941 fm->next_ack = GNUNET_TIME_absolute_get();
943 if (pm->transmit_cont != NULL)
944 pm->transmit_cont (pm->transmit_cont_cls,
945 &(session->target), GNUNET_OK);
948 sort_fragment_into_queue(plugin,fm);
949 plugin->pending_fragment_messages ++;
951 //generate new message id
952 session->message_id_out = get_next_message_id();
954 //check if timeout changed
955 check_next_fragment_timeout(plugin);
962 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
963 struct AckQueue * ack;
966 if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
967 * fm->tail->fragment_num)
971 //check if all acks are present
974 if (counter == ack->fragment_num)
983 fm->session->has_fragment = 0;
984 free_fragment_message(plugin, fm);
991 * Function called to when wlan helper is ready to get some data
994 * @param GNUNET_SCHEDULER_TaskContext
998 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1001 struct Plugin * plugin = cls;
1002 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1006 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1009 struct Session * session = NULL;
1010 struct FragmentMessage * fm = NULL;
1011 struct IeeeHeader * ieeewlanheader = NULL;
1012 struct RadiotapHeader * radioHeader = NULL;
1013 struct GNUNET_MessageHeader * msgheader = NULL;
1014 struct GNUNET_MessageHeader * msgheader2 = NULL;
1015 struct FragmentationHeader fragheader;
1017 const char * copystart = NULL;
1018 uint16_t copysize = 0;
1019 uint copyoffset = 0;
1020 struct AckQueue * akt = NULL;
1022 //test if a "hello-beacon" has to be send
1023 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1025 //check if the message is not to big
1026 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1027 *(plugin->env->our_hello)) <= WLAN_MTU);
1028 size = sizeof(struct GNUNET_MessageHeader)
1029 + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1030 + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1031 *(plugin->env->our_hello));
1033 msgheader = GNUNET_malloc(size);
1034 msgheader->size = htons(size);
1035 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1037 radioHeader = (struct RadiotapHeader *) &msgheader[1];
1038 getRadiotapHeader(radioHeader);
1040 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1041 getWlanHeader(ieeewlanheader);
1043 msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1044 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello)) + sizeof(struct GNUNET_MessageHeader));
1045 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1047 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1048 *(plugin->env->our_hello)));
1051 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1053 GNUNET_assert(bytes == size);
1055 set_next_beacon_time(plugin);
1056 check_next_fragment_timeout(plugin);
1062 fm = plugin->pending_Fragment_Messages_head;
1063 GNUNET_assert(fm != NULL);
1064 session = fm->session;
1065 GNUNET_assert(session != NULL);
1067 // test if message timed out
1068 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
1070 GNUNET_assert(plugin->pending_fragment_messages > 0);
1071 plugin->pending_fragment_messages --;
1072 GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1073 plugin->pending_Fragment_Messages_tail, fm);
1075 GNUNET_free(fm->msg);
1078 check_fragment_queue(plugin);
1081 if (fm->message_size > WLAN_MTU) {
1082 size += sizeof(struct FragmentationHeader);
1083 // check/set for retransmission
1084 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
1086 // be positive and try again later :-D
1087 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1088 // find first missing fragment
1090 fm->message_pos = 0;
1092 //test if ack 0 was already received
1093 while (akt != NULL){
1094 //if fragment is present, take next
1095 if (akt->fragment_num == fm->message_pos) {
1098 //next ack is bigger then the fragment number
1099 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1100 //and we send 3 again, the next number should be 4
1101 else if (akt->fragment_num > fm->message_pos) {
1112 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
1113 fragheader.fragment_off_or_num = htons(fm->message_pos);
1114 fragheader.message_id = htonl(session->message_id_out);
1116 // start should be smaller then the packet size
1117 GNUNET_assert(copyoffset < fm->message_size);
1118 copystart = fm->msg + copyoffset;
1120 //size of the fragment is either the MTU - overhead
1121 //or the missing part of the message in case this is the last fragment
1122 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1123 WLAN_MTU - sizeof(struct FragmentationHeader));
1124 fragheader.header.size = htons(copysize + sizeof(struct FragmentationHeader));
1125 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1128 //get the next missing fragment
1132 //test if ack was already received
1133 while (akt != NULL){
1134 //if fragment is present, take next
1135 if (akt->fragment_num == fm->message_pos) {
1138 //next ack is bigger then the fragment number
1139 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1140 //and we send 3 again, the next number should be 4
1141 else if (akt->fragment_num > fm->message_pos) {
1148 // there is no need to split
1149 copystart = fm->msg;
1150 copysize = fm->message_size;
1154 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1155 + sizeof(struct GNUNET_MessageHeader);
1156 msgheader = GNUNET_malloc(size);
1157 msgheader->size = htons(size);
1158 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1160 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1161 getRadiotapHeader(radioHeader);
1163 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1164 getWlanHeader(ieeewlanheader);
1167 //could be faster if content is just send and not copyed before
1168 //fragmentheader is needed
1169 if (fm->message_size > WLAN_MTU){
1170 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1171 memcpy(&ieeewlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
1172 memcpy(&ieeewlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
1174 memcpy(&ieeewlanheader[1],copystart,copysize);
1177 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1178 GNUNET_assert(bytes == size);
1180 //check if this was the last fragment of this message, if true then queue at the end of the list
1181 if (copysize + copyoffset >= fm->message_size){
1182 GNUNET_assert(copysize + copyoffset == fm->message_size);
1184 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1185 plugin->pending_Fragment_Messages_tail, fm);
1187 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1188 plugin->pending_Fragment_Messages_tail, fm);
1189 // if fragments have opimized timeouts
1190 //sort_fragment_into_queue(plugin,fm);
1193 check_next_fragment_timeout(plugin);
1202 * @param msgbuf pointer tor the data
1203 * @param msgbuf_size size of the data
1205 * @return 32bit crc value
1209 getcrc32 (const char *msgbuf,
1210 size_t msgbuf_size){
1211 //TODO calc some crc
1218 * @param msgbuf pointer tor the data
1219 * @param msgbuf_size size of the data
1221 * @return 16bit crc value
1225 getcrc16 (const char *msgbuf,
1226 size_t msgbuf_size){
1227 //TODO calc some crc
1232 * Function that can be used by the transport service to transmit
1233 * a message using the plugin.
1235 * @param cls closure
1236 * @param target who should receive this message
1237 * @param priority how important is the message
1238 * @param msgbuf the message to transmit
1239 * @param msgbuf_size number of bytes in 'msgbuf'
1240 * @param timeout when should we time out
1241 * @param session which session must be used (or NULL for "any")
1242 * @param addr the address to use (can be NULL if the plugin
1243 * is "on its own" (i.e. re-use existing TCP connection))
1244 * @param addrlen length of the address in bytes
1245 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1246 * otherwise the plugin may use other addresses or
1247 * existing connections (if available)
1248 * @param cont continuation to call once the message has
1249 * been transmitted (or if the transport is ready
1250 * for the next transmission call; or if the
1251 * peer disconnected...)
1252 * @param cont_cls closure for cont
1253 * @return number of bytes used (on the physical network, with overheads);
1254 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1255 * and does NOT mean that the message was not transmitted (DV)
1258 wlan_plugin_send (void *cls,
1259 const struct GNUNET_PeerIdentity * target,
1262 unsigned int priority,
1263 struct GNUNET_TIME_Relative timeout,
1264 struct Session *session,
1268 GNUNET_TRANSPORT_TransmitContinuation cont,
1271 struct Plugin * plugin = cls;
1272 struct PendingMessage * newmsg = NULL;
1273 struct WlanHeader * wlanheader = NULL;
1274 //check if msglen > 0
1275 GNUNET_assert(msgbuf_size > 0);
1277 //get session if needed
1278 if (session == NULL)
1280 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1282 session = get_Session(plugin, addr);
1286 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1287 _("Wlan Address len %d is wrong\n"), addrlen);
1292 //TODO target "problem" not solved
1293 session->target = *target;
1296 //first queue session
1297 queue_Session(plugin, session);
1299 //queue message in session
1300 //test if there is no other message in the "queue"
1301 GNUNET_assert (session->pending_message == NULL);
1303 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1304 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1305 wlanheader = (struct WlanHeader *) newmsg->msg;
1306 //copy msg to buffer, not fragmented / segmented yet, but with message header
1307 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1308 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1309 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1310 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1311 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1312 newmsg->transmit_cont = cont;
1313 newmsg->transmit_cont_cls = cont_cls;
1314 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1315 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1317 check_fragment_queue(plugin);
1318 //FIXME not the correct size
1324 static struct FragmentMessage *
1325 get_fragment_message_from_session(struct Session * session)
1327 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1330 if (fm->session == session)
1340 * Function that can be used to force the plugin to disconnect
1341 * from the given peer and cancel all previous transmissions
1342 * (and their continuation).
1344 * @param cls closure
1345 * @param target peer from which to disconnect
1348 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1350 struct Plugin *plugin = cls;
1351 struct Sessionqueue * queue = plugin->sessions;
1352 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1353 struct PendingMessage * pm = NULL;
1354 struct FragmentMessage * fm;
1356 // just look at all the session for the needed one
1357 while (queue != NULL)
1359 // content is never NULL
1360 GNUNET_assert (queue->content == NULL);
1361 if (memcmp(target, &(queue->content->target),
1362 sizeof(struct GNUNET_PeerIdentity)) == 0)
1365 //is this session pending for send
1366 while (pendingsession != NULL)
1368 if (pendingsession->content == queue->content)
1370 plugin->pendingsessions --;
1371 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1372 plugin->pending_Sessions_tail, pendingsession);
1373 GNUNET_free(pendingsession);
1376 pendingsession = pendingsession->next;
1379 //is something of this session in the fragment queue?
1380 fm = get_fragment_message_from_session(queue->content);
1381 free_fragment_message(plugin,fm);
1383 //dispose all received fragments
1384 free_rec_frag_queue(queue->content);
1386 // remove PendingMessage
1387 pm = queue->content->pending_message;
1388 GNUNET_free(pm->msg);
1391 GNUNET_free(queue->content);
1392 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1394 plugin->session_count --;
1399 queue = queue->next;
1405 * Convert the transports address to a nice, human-readable
1408 * @param cls closure
1409 * @param type name of the transport that generated the address
1410 * @param addr one of the addresses of the host, NULL for the last address
1411 * the specific address format depends on the transport
1412 * @param addrlen length of the address
1413 * @param numeric should (IP) addresses be displayed in numeric form?
1414 * @param timeout after how long should we give up?
1415 * @param asc function to call on each string
1416 * @param asc_cls closure for asc
1419 wlan_plugin_address_pretty_printer (void *cls,
1424 struct GNUNET_TIME_Relative timeout,
1425 GNUNET_TRANSPORT_AddressStringCallback
1429 const unsigned char * input;
1431 GNUNET_assert(cls !=NULL);
1434 /* invalid address (MAC addresses have 6 bytes) */
1436 asc (asc_cls, NULL);
1439 input = (const unsigned char*) addr;
1440 GNUNET_snprintf (ret,
1442 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1444 input[0], input[1], input[2], input[3], input[4], input[5]);
1451 * Another peer has suggested an address for this
1452 * peer and transport plugin. Check that this could be a valid
1453 * address. If so, consider adding it to the list
1456 * @param cls closure
1457 * @param addr pointer to the address
1458 * @param addrlen length of addr
1459 * @return GNUNET_OK if this is a plausible address for this peer
1465 wlan_plugin_address_suggested (void *cls,
1469 //struct Plugin *plugin = cls;
1471 /* check if the address is plausible; if so,
1472 add it to our list! */
1474 GNUNET_assert(cls !=NULL);
1475 //FIXME mitm is not checked
1476 //Mac Adress has 6 bytes
1478 /* TODO check for bad addresses like milticast, broadcast, etc */
1481 return GNUNET_SYSERR;
1484 return GNUNET_SYSERR;
1489 * Function called for a quick conversion of the binary address to
1490 * a numeric address. Note that the caller must not free the
1491 * address and that the next call to this function is allowed
1492 * to override the address again.
1494 * @param cls closure
1495 * @param addr binary address
1496 * @param addrlen length of the address
1497 * @return string representing the same address
1500 wlan_plugin_address_to_string (void *cls,
1505 const unsigned char * input;
1507 GNUNET_assert(cls !=NULL);
1510 /* invalid address (MAC addresses have 6 bytes) */
1514 input = (const unsigned char*) addr;
1515 GNUNET_snprintf (ret,
1517 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1519 input[0], input[1], input[2], input[3], input[4], input[5]);
1520 return GNUNET_strdup (ret);
1524 * Function to test if fragment number already exists in the fragments received
1528 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1530 struct RecQueue * rec_queue = session->frag_head;
1531 while (rec_queue != NULL)
1533 if (rec_queue->num == fh->fragment_off_or_num)
1537 rec_queue = rec_queue->next;
1545 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1547 struct RecQueue * rec_queue2 = session->frag_head;
1548 struct WlanHeader * wlanheader = NULL;
1549 //first received fragment of message
1550 if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1552 session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1554 //this is the first fragment of the message (fragment id 0)
1555 if (rec_queue->num == 0)
1557 wlanheader = (struct WlanHeader *) rec_queue->msg;
1558 session->rec_size = wlanheader->header.size;
1562 while (rec_queue2 != NULL)
1564 if (rec_queue2->num > rec_queue->num)
1566 //next element number is grater than the current num
1567 GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1570 rec_queue = rec_queue->next;
1572 //no element has a grater number
1573 GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1577 * Function to dispose the fragments received for a message
1581 free_rec_frag_queue(struct Session * session)
1583 struct RecQueue * rec_queue = session->frag_head;
1584 struct RecQueue * rec_queue2;
1585 while (rec_queue != NULL)
1587 rec_queue2 = rec_queue;
1588 rec_queue = rec_queue->next;
1589 GNUNET_free(rec_queue2);
1591 session->frag_head = NULL;
1592 session->frag_tail = NULL;
1593 session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1597 * Function to check if all fragments of a message have been received
1601 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1602 struct RecQueue * rec_queue = session->frag_head;
1603 int packetsize = session->rec_size;
1607 //some fragment should be received
1608 GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1609 //check if first fragment is present
1610 if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1613 while (rec_queue != NULL){
1614 sum += rec_queue->size;
1615 //check if all fragment numbers are present
1616 if (rec_queue->num != aktnum){
1620 rec_queue = rec_queue->next;
1622 //sum should always be smaller or equal of
1623 GNUNET_assert(sum <= packetsize);
1624 if (sum == packetsize){
1625 //copy fragments together
1626 msg = GNUNET_malloc(packetsize);
1627 rec_queue = session->frag_head;
1629 while (rec_queue != NULL){
1630 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1631 aktnum += rec_queue->size;
1632 rec_queue = rec_queue->next;
1634 free_rec_frag_queue(session);
1635 //call wlan_process_helper to process the message
1636 wlan_process_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1643 * Function used for to process the data from the suid process
1648 wlan_process_helper (void *cls,
1650 const struct GNUNET_MessageHeader *hdr)
1652 struct Plugin *plugin = cls;
1653 struct IeeeHeader * wlanIeeeHeader = NULL;
1654 struct Session * session = NULL;
1655 struct WlanHeader * wlanheader = NULL;
1656 struct FragmentationHeader * fh = NULL;
1657 struct FragmentMessage * fm = NULL;
1658 struct RecQueue * rec_queue = NULL;
1659 const struct GNUNET_MessageHeader * temp_hdr = NULL;
1660 const char * tempmsg = NULL;
1661 struct Session_light * session_light;
1662 struct AckQueue * ack;
1663 struct AckQueue * ack2;
1667 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
1669 //call wlan_process_helper with the message inside, later with wlan: analyze signal
1670 GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
1671 wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
1673 session_light = GNUNET_malloc(sizeof(struct Session_light));
1674 memcpy(session_light->addr, wlanIeeeHeader->mac3, 6);
1675 session_light->session = search_session(plugin, session_light->addr);
1677 //process only if it is an broadcast or for this computer both with the gnunet bssid
1679 if (memcmp(wlanIeeeHeader->mac2, macbc, sizeof(macbc)))
1681 //check for broadcast or mac
1682 if (memcmp(wlanIeeeHeader->mac1, bc_all_mac, sizeof(bc_all_mac))
1683 || memcmp(wlanIeeeHeader->mac1, plugin->mac_address,
1684 sizeof(plugin->mac_address)))
1686 // process the inner data
1688 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
1689 while (pos < hdr->size)
1691 wlan_process_helper(plugin, &session_light,
1693 pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
1701 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1703 //TODO better DOS protection, error handling
1704 GNUNET_assert(client != NULL);
1705 session_light = (struct Session_light *) client;
1706 if (session_light->session == NULL){
1707 session_light->session = get_Session(plugin, session_light->addr);
1709 GNUNET_assert(GNUNET_HELLO_get_id(
1710 (const struct GNUNET_HELLO_Message *) &hdr[1],
1711 &(session_light->session->target) ) != GNUNET_SYSERR);
1716 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1718 GNUNET_assert(client != NULL);
1719 session_light = (struct Session_light *) client;
1720 if (session_light->session == NULL){
1721 session_light->session = search_session(plugin, session_light->addr);
1723 session = session_light->session;
1724 wlanheader =(struct WlanHeader *) &hdr[1];
1725 tempmsg = (char*) &wlanheader[1];
1726 temp_hdr = ( const struct GNUNET_MessageHeader *) &wlanheader[1];
1728 if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc){
1729 //wrong crc, dispose message
1730 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1731 "WLAN message crc was wrong\n");
1735 //if not in session list
1736 if (session == NULL){
1738 //try if it is a hello message
1739 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO){
1740 session = create_session(plugin, session_light->addr);
1741 session_light->session = session;
1742 GNUNET_assert(GNUNET_HELLO_get_id(
1743 (const struct GNUNET_HELLO_Message *) temp_hdr,
1744 &session->target ) != GNUNET_SYSERR);
1747 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1748 "WLAN client not in session list and not a hello message\n");
1752 //"receive" the message
1753 struct GNUNET_TRANSPORT_ATS_Information distance[2];
1754 distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1755 distance[0].value = htonl (1);
1756 distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1757 distance[1].value = htonl (0);
1759 plugin->env->receive(plugin, &session->target,
1760 temp_hdr, (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1761 session, session->addr, sizeof(session->addr));
1764 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1766 GNUNET_assert(client != NULL);
1767 session_light = (struct Session_light *) client;
1768 if (session_light->session == NULL)
1770 session_light->session = search_session(plugin, session_light->addr);
1772 session = session_light->session;
1774 fh = (struct FragmentationHeader *) hdr;
1775 tempmsg = (char*) &fh[1];
1777 //if not in session list
1778 if (session != NULL)
1780 if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1782 //wrong crc, dispose message
1783 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1784 "WLAN fragment crc was wrong\n");
1789 //todo fragments do not timeout
1790 //check if message_id is rigth or it is a new msg
1791 if ((session->message_id_in == ntohs(fh->message_id))
1792 || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1794 session->message_id_in = ntohs(fh->message_id);
1795 if (is_double_msg(session, fh) != GNUNET_YES)
1797 rec_queue = GNUNET_malloc(sizeof (struct RecQueue) +
1798 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1799 rec_queue->size = ntohs(fh->header.size
1800 - sizeof(struct FragmentationHeader));
1801 rec_queue->num = ntohs(fh->fragment_off_or_num);
1802 rec_queue->msg = (char*) &rec_queue[1];
1803 //copy msg to buffer
1804 memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1805 insert_fragment_in_queue(session, rec_queue);
1806 check_rec_finished_msg(plugin, session_light, session);
1810 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1811 "WLAN fragment is a clone\n");
1817 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1818 "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
1825 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1826 "WLAN client not in session list and it is a fragment message\n");
1832 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1834 GNUNET_assert(client != NULL);
1835 session_light = (struct Session_light *) client;
1836 if (session_light->session == NULL)
1838 session_light->session = search_session(plugin, session_light->addr);
1840 session = session_light->session;
1841 fh = (struct FragmentationHeader *) &hdr[1];
1842 if (fh->message_id == session->message_id_out)
1844 fm = get_fragment_message_from_session(session);
1847 ack = GNUNET_malloc(sizeof(struct AckQueue));
1848 ack->fragment_num = fh->fragment_off_or_num;
1851 if (ack2->fragment_num != ack->fragment_num)
1853 if (ack2->fragment_num > ack->fragment_num)
1855 GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
1857 check_finished_fragment(plugin, fm);
1867 GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
1868 //should never happen but...
1869 check_finished_fragment(plugin, fm);
1873 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1874 "WLAN fragment not in fragment list but id is right\n");
1882 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
1885 if (ntohs(hdr->size) == 6)
1887 plugin->mac_address = GNUNET_malloc(6);
1888 memcpy(plugin->mac_address, &hdr[1], 6);
1890 GNUNET_ERROR_TYPE_DEBUG,
1891 "Notifying transport of address %s\n",
1892 wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1893 plugin->env->notify_address(plugin->env->cls, "wlan",
1894 &plugin->mac_address, sizeof(plugin->mac_address),
1895 GNUNET_TIME_UNIT_FOREVER_REL);
1899 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
1900 plugin->mac_address);
1909 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN packet has not the right type\n");
1916 wlan_plugin_helper_read (void *cls,
1917 const struct GNUNET_SCHEDULER_TaskContext *tc)
1919 struct Plugin *plugin = cls;
1920 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1922 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
1925 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1928 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1929 mybuf, sizeof(mybuf));
1933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1934 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1938 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1939 mybuf, bytes, GNUNET_NO, GNUNET_NO);
1941 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1942 plugin->server_read_task =
1943 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1944 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1949 * Start the gnunet-wlan-helper process.
1951 * @param plugin the transport plugin
1953 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1956 wlan_transport_start_wlan_helper(struct Plugin *plugin)
1959 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1960 if (plugin->server_stdout == NULL)
1961 return GNUNET_SYSERR;
1963 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
1964 if (plugin->server_stdin == NULL)
1965 return GNUNET_SYSERR;
1968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1969 "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1971 /* Start the server process */
1972 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
1973 plugin->server_stdout, "gnunet-transport-wlan-helper",
1974 "gnunet-transport-wlan-helper", plugin->interface, NULL);
1975 if (plugin->server_proc == NULL)
1978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1979 "Failed to start gnunet-wlan-helper process\n");
1981 return GNUNET_SYSERR;
1983 /* Close the write end of the read pipe */
1984 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1986 /* Close the read end of the write pipe */
1987 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1989 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
1990 GNUNET_DISK_PIPE_END_READ);
1991 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
1992 GNUNET_DISK_PIPE_END_WRITE);
1994 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1995 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
1996 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
1997 &wlan_plugin_helper_read, plugin);
2004 * Entry point for the plugin.
2006 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2007 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2010 libgnunet_plugin_transport_wlan_init (void *cls)
2012 struct GNUNET_SERVICE_Context *service;
2013 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2014 struct GNUNET_TRANSPORT_PluginFunctions *api;
2015 struct Plugin *plugin;
2017 GNUNET_assert(cls !=NULL);
2019 service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
2020 if (service == NULL){
2021 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2022 _("Failed to start service for `%s' transport plugin.\n"),
2027 plugin = GNUNET_malloc (sizeof (struct Plugin));
2029 plugin->pendingsessions = 0;
2030 plugin->session_count = 0;
2031 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2032 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2033 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2035 wlan_transport_start_wlan_helper(plugin);
2036 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2038 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2039 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2041 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2043 api->send = &wlan_plugin_send;
2044 api->disconnect = &wlan_plugin_disconnect;
2045 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2046 api->check_address = &wlan_plugin_address_suggested;
2047 api->address_to_string = &wlan_plugin_address_to_string;
2050 start_next_message_id();
2057 * Exit point from the plugin.
2062 libgnunet_plugin_transport_wlan_done (void *cls)
2064 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2065 struct Plugin *plugin = api->cls;
2067 GNUNET_assert(cls !=NULL);
2069 GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2071 GNUNET_free_non_null(plugin->mac_address);
2072 GNUNET_free (plugin);
2077 /* end of plugin_transport_wlan.c */