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"
37 #include "wlan/ieee80211.h"
41 #define PROTOCOL_PREFIX "wlan"
44 * Max size of packet from helper
49 * Time until retransmission of a fragment in ms
51 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
53 #define FRAGMENT_QUEUE_SIZE 10
54 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
56 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
58 #define MESSAGES_IN_QUEUE_SIZE 10
59 #define MESSAGES_IN_QUEUE_PER_SESSION 1
61 #define HALLO_BEACON_SCALING_FACTOR 900
63 #define DEBUG_wlan GNUNET_NO
65 #define MESSAGE_LENGHT_UNKNOWN -1
66 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
69 * After how long do we expire an address that we
70 * learned from another peer if it is not reconfirmed
73 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
76 * Initial handshake message for a session.
81 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
83 struct GNUNET_MessageHeader header;
86 * Identit*mac_y of the node connecting (TCP client)
88 struct GNUNET_PeerIdentity clientIdentity;
93 * Encapsulation of all of the state of the plugin.
100 struct GNUNET_TRANSPORT_PluginEnvironment *env;
103 * List of open sessions. head
105 struct Sessionqueue *sessions;
108 * List of open sessions. tail
110 struct Sessionqueue *sessions_tail;
115 unsigned int session_count;
118 * encapsulation of data from the local wlan helper program
120 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
123 * encapsulation of packets received
125 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
128 * stdout pipe handle for the gnunet-wlan-helper process
130 struct GNUNET_DISK_PipeHandle *server_stdout;
133 * stdout file handle for the gnunet-wlan-helper process
135 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
138 * stdin pipe handle for the gnunet-wlan-helper process
140 struct GNUNET_DISK_PipeHandle *server_stdin;
143 * stdin file handle for the gnunet-wlan-helper process
145 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
148 * ID of the gnunet-wlan-server std read task
150 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
153 * ID of the gnunet-wlan-server std read task
155 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
158 * ID of the delay task for writing
160 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
163 * The process id of the wlan process
165 struct GNUNET_OS_Process *server_proc;
168 * The interface of the wlan card given to us by the user.
173 * The mac_address of the wlan card given to us by the helper.
175 struct MacAddress mac_address;
178 * Sessions currently pending for transmission
179 * to this peer, if any.
181 struct Sessionqueue * pending_Sessions;
184 * Sessions currently pending for transmission
185 * to this peer (tail), if any.
187 struct Sessionqueue * pending_Sessions_tail;
190 * number of pending sessions
192 unsigned int pendingsessions;
195 * Messages in the fragmentation queue, head
197 struct FragmentMessage * pending_Fragment_Messages_head;
200 * Messages in the fragmentation queue, tail
202 struct FragmentMessage * pending_Fragment_Messages_tail;
205 * number of pending fragment message
207 unsigned int pending_fragment_messages;
210 * Messages in the in Queue, head
212 struct Receive_Message_Queue * receive_messages_head;
215 * Messages in the in Queue, tail
217 struct Receive_Message_Queue * receive_messages_teil;
220 * number of messages in the in queue
222 unsigned int pending_receive_messages;
225 * time of the next "hello-beacon"
227 struct GNUNET_TIME_Absolute beacon_time;
230 * queue to send acks for received fragments (head)
232 struct AckSendQueue * ack_send_queue_head;
235 * queue to send acks for received fragments (tail)
237 struct AckSendQueue * ack_send_queue_tail;
242 * Struct to store data if file write did not accept the whole packet
246 struct Plugin * plugin;
248 struct GNUNET_MessageHeader * msgstart;
253 * Queue of sessions, for the general session queue and the pending session queue
258 struct Sessionqueue * next;
259 struct Sessionqueue * prev;
260 struct Session * content;
264 * Queue for the fragments received
266 struct Receive_Fragment_Queue
268 struct Receive_Fragment_Queue * next;
269 struct Receive_Fragment_Queue * prev;
273 struct Radiotap_rx rxinfo;
278 * Queue for the fragments received
280 struct Receive_Message_Queue
282 struct Receive_Message_Queue * next;
284 struct Receive_Message_Queue * prev;
287 * current number for message incoming, to distinguish between the messages
289 uint32_t message_id_in;
292 * size of the message received,
293 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
294 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
299 * Sorted queue with the fragments received; head
302 struct Receive_Fragment_Queue * frag_head;
305 * Sorted queue with the fragments received; tail
308 struct Receive_Fragment_Queue * frag_tail;
311 * Session this fragment belongs to
314 struct Session * session;
317 * Timeout value for the pending message.
319 struct GNUNET_TIME_Absolute timeout;
322 * Bitfield of received fragments
325 uint64_t received_fragments;
329 * Information kept for each message that is yet to
332 struct PendingMessage
336 * The pending message
341 * Size of the message
346 * Continuation function to call once the message
347 * has been sent. Can be NULL if there is no
348 * continuation to call.
350 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
353 * Cls for transmit_cont
355 void * transmit_cont_cls;
358 * Timeout value for the pending message.
360 struct GNUNET_TIME_Absolute timeout;
365 * Queue for acks to send for fragments recived
371 struct AckSendQueue * next;
372 struct AckSendQueue * prev;
374 struct Session * session;
376 * ID of message, to distinguish between the messages, picked randomly.
381 * Bit field for received fragments
383 uint64_t fragments_field;
388 * Session infos gathered from a messages
394 * the session this message belongs to
396 struct Session * session;
400 struct MacAddress addr;
404 * Session handle for connections.
412 struct SessionHeader header;
415 * Pointer to the global plugin struct.
417 struct Plugin *plugin;
420 * Message currently pending for transmission
421 * to this peer, if any.
423 struct PendingMessage *pending_message;
426 * Message currently pending for transmission
427 * to this peer, if any.
429 struct PendingMessage *pending_message2;
432 * To whom are we talking to (set to our identity
433 * if we are still waiting for the welcome message)
435 struct GNUNET_PeerIdentity target;
440 struct MacAddress addr;
443 * Address of the other peer (either based on our 'connect'
444 * call or on our 'accept' call).
449 * Last activity on this connection. Used to select preferred
452 struct GNUNET_TIME_Absolute last_activity;
455 * count of messages in the fragment out queue for this session
458 int fragment_messages_out_count;
461 * count of messages in the fragment in queue for this session
464 int fragment_messages_in_count;
474 * Struct for Messages in the fragment queue
477 struct FragmentMessage
480 * Session this message belongs to
483 struct Session *session;
486 * This is a doubly-linked list.
488 struct FragmentMessage *next;
491 * This is a doubly-linked list.
493 struct FragmentMessage *prev;
496 * The pending message
501 * Timeout value for the pending message.
503 struct GNUNET_TIME_Absolute timeout;
506 * Timeout value for the pending fragments.
507 * Stores the time when the next msg fragment ack has to be received
509 struct GNUNET_TIME_Absolute next_ack;
512 * bitfield with all acks received for this message
514 uint64_t ack_bitfield;
517 * Size of the message
522 * pos / next fragment number in the message, for fragmentation/segmentation,
523 * some acks can be missing but there is still time
525 uint32_t message_pos;
528 * current number for message outgoing, to distinguish between the messages
530 uint32_t message_id_out;
534 * Header for messages which need fragmentation
536 struct FragmentationAckHeader
539 struct GNUNET_MessageHeader header;
542 * ID of message, to distinguish between the messages, picked randomly.
544 uint32_t message_id GNUNET_PACKED;
547 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
549 uint64_t fragment_field GNUNET_PACKED;
554 do_transmit(void *cls,
555 const struct GNUNET_SCHEDULER_TaskContext *tc);
560 * Sets a bit active in the bitArray. Increment bit-specific
561 * usage counter on disk only if below 4bit max (==15).
563 * @param bitArray memory area to set the bit in
564 * @param bitIdx which bit to set
567 setBit(char *bitArray, unsigned int bitIdx)
570 unsigned int targetBit;
572 arraySlot = bitIdx / 8;
573 targetBit = (1L << (bitIdx % 8));
574 bitArray[arraySlot] |= targetBit;
579 * Checks if a bit is active in the bitArray
581 * @param bitArray memory area to set the bit in
582 * @param bitIdx which bit to test
583 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
586 testBit(char *bitArray, unsigned int bitIdx)
589 unsigned int targetBit;
592 targetBit = (1L << (bitIdx % 8));
593 if (bitArray[slot] & targetBit)
599 * get the next message number, at the moment just a random one
600 * @return returns the next valid message-number for sending packets
603 get_next_message_id()
605 return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
610 * search for a session with the addr
612 * @param plugin pointer to the plugin struct
613 * @param addr pointer to the mac address of the peer
614 * @return returns the session
616 static struct Session *
617 search_session(struct Plugin *plugin,
618 const struct MacAddress *addr)
620 struct Sessionqueue * queue = plugin->sessions;
622 while (queue != NULL)
624 GNUNET_assert (queue->content != NULL);
625 if (memcmp(addr, &queue->content->addr, sizeof (struct MacAddress)) == 0)
626 return queue->content; /* session found */
633 * create a new session
635 * @param plugin pointer to the plugin struct
636 * @param addr pointer to the mac address of the peer
637 * @return returns the session
640 static struct Session *
641 create_session(struct Plugin *plugin,
642 const struct MacAddress * addr)
644 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
646 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
648 queue->content = GNUNET_malloc (sizeof (struct Session));
649 queue->content->plugin = plugin;
650 queue->content->addr = *addr;
651 queue->content->fragment_messages_out_count = 0;
652 queue->content->fragment_messages_in_count = 0;
654 plugin->session_count++;
657 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
658 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
661 return queue->content;
666 * Get session from address, create if no session exists
668 * @param plugin pointer to the plugin struct
669 * @param addr pointer to the mac address of the peer
670 * @return returns the session
672 static struct Session *
673 get_Session (struct Plugin *plugin,
674 const struct MacAddress *addr)
676 struct Session * session = search_session(plugin, addr);
679 return create_session(plugin, addr);
684 * Queue the session to send data
688 queue_Session(struct Plugin *plugin, struct Session * session)
690 struct Sessionqueue * queue = plugin->pending_Sessions;
691 struct Sessionqueue * lastitem = NULL;
693 while (queue != NULL)
695 // content is never NULL
696 GNUNET_assert (queue->content != NULL);
697 // is session already in queue?
698 if (session == queue->content)
707 // Session is not in the queue
709 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
710 queue->content = session;
713 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
714 plugin->pending_Sessions_tail,
715 plugin->pending_Sessions_tail, queue);
716 plugin->pendingsessions++;
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_relative_multiply(
754 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
756 //under 30 known peers: every 10 seconds
757 else if (plugin->session_count < 30)
759 plugin->beacon_time = GNUNET_TIME_absolute_add(
760 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
761 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
763 //over 30 known peers: once a minute
766 plugin->beacon_time = GNUNET_TIME_absolute_add(
767 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
768 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
773 static struct GNUNET_TIME_Relative
774 get_next_frag_timeout(struct FragmentMessage * fm)
776 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
777 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
782 * Function to get the timeout value for acks for this session
785 static struct GNUNET_TIME_Relative
786 get_ack_timeout(struct FragmentMessage * fm)
788 return FRAGMENT_TIMEOUT;
792 * Function to set the timer for the next timeout of the fragment queue
793 * @param plugin the handle to the plugin struct
796 check_next_fragment_timeout(struct Plugin * const plugin)
798 struct FragmentMessage * fm;
799 struct GNUNET_TIME_Relative next_send;
802 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
804 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
805 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
807 fm = plugin->pending_Fragment_Messages_head;
809 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
811 //check if some acks are in the queue
812 if (plugin->ack_send_queue_head != NULL)
814 next_send = GNUNET_TIME_UNIT_ZERO;
816 //check if there are some fragments in the queue
819 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
822 next_send = GNUNET_TIME_relative_min(next_send,
823 get_next_frag_timeout(fm));
826 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
827 &delay_fragment_task, plugin);
832 * Function to get the next queued Session, removes the session from the queue
835 static struct Session *
836 get_next_queue_Session(struct Plugin * plugin)
838 struct Session * session;
839 struct Sessionqueue * sessionqueue;
840 struct Sessionqueue * sessionqueue_alt;
841 struct PendingMessage * pm;
842 sessionqueue = plugin->pending_Sessions;
843 while (sessionqueue != NULL)
845 session = sessionqueue->content;
847 pm = session->pending_message;
851 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
852 "pending message is empty, should not happen. session %p\n",
856 GNUNET_assert(pm != NULL);
858 //check for message timeout
859 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
861 //check if session has no message in the fragment queue
862 if (session->fragment_messages_out_count
863 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
865 plugin->pendingsessions--;
866 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
867 plugin->pending_Sessions_tail, sessionqueue);
868 GNUNET_free(sessionqueue);
874 sessionqueue = sessionqueue->next;
880 session->pending_message = session->pending_message2;
881 session->pending_message2 = NULL;
883 //call the cont func that it did not work
884 if (pm->transmit_cont != NULL)
885 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
887 GNUNET_free(pm->msg);
890 if (session->pending_message == NULL)
892 sessionqueue_alt = sessionqueue;
893 sessionqueue = sessionqueue->next;
894 plugin->pendingsessions--;
895 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
896 plugin->pending_Sessions_tail, sessionqueue_alt);
898 GNUNET_free(sessionqueue_alt);
908 * Function to sort the message into the message fragment queue
909 * @param plugin the plugin struct
910 * @param fm message to sort into the queue
913 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
915 struct FragmentMessage * fm2;
916 //sort into the list at the right position
918 fm2 = plugin->pending_Fragment_Messages_head;
922 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
925 GNUNET_CONTAINER_DLL_insert_before(plugin->pending_Fragment_Messages_head,
926 plugin->pending_Fragment_Messages_tail,fm2,fm);
935 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
936 plugin->pending_Fragment_Messages_tail,fm);
940 * frees the space of a message in the fragment queue (send queue)
941 * @param plugin the plugin struct
942 * @param fm message to free
945 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
949 (fm->session->fragment_messages_out_count)--;
950 GNUNET_free_non_null(fm->msg);
951 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
952 plugin->pending_Fragment_Messages_tail, fm);
954 plugin->pending_fragment_messages--;
957 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
958 "free pending fragment messages, pending messages remaining %u\n",
959 plugin->pending_fragment_messages);
965 * Function to check if there is some space in the fragment queue
966 * inserts a message if space is available
967 * @param plugin the plugin struct
971 check_fragment_queue(struct Plugin * plugin)
973 struct Session * session;
974 struct FragmentMessage * fm;
975 struct GNUNET_PeerIdentity pid;
977 struct PendingMessage * pm;
979 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
981 session = get_next_queue_Session(plugin);
984 pm = session->pending_message;
985 session->pending_message = NULL;
986 session->fragment_messages_out_count++;
987 GNUNET_assert(pm != NULL);
989 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
990 fm->message_size = pm->message_size;
992 fm->session = session;
993 fm->timeout.abs_value = pm->timeout.abs_value;
995 fm->next_ack = GNUNET_TIME_absolute_get();
996 fm->message_id_out = get_next_message_id();
997 fm->ack_bitfield = 0;
999 sort_fragment_into_queue(plugin, fm);
1000 plugin->pending_fragment_messages++;
1002 if (pm->transmit_cont != NULL)
1004 pid = session->target;
1005 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1007 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1008 "called pm->transmit_cont for %p\n", session);
1014 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1015 "no pm->transmit_cont for %p\n", session);
1020 if (session->pending_message2 != NULL)
1022 session->pending_message = session->pending_message2;
1023 session->pending_message2 = NULL;
1025 queue_Session(plugin, session);
1028 //check if timeout changed
1029 check_next_fragment_timeout(plugin);
1035 * Funktion to check if all fragments where send and the acks received
1036 * frees the space if finished
1037 * @param plugin the plugin struct
1038 * @param fm the message to check
1041 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1043 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1044 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1045 - sizeof(struct FragmentationHeader)));
1046 uint64_t tmpfield = UINT64_MAX;
1047 tmpfield = tmpfield >> maxack;
1051 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1052 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1053 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1056 if (fm->ack_bitfield == tmpfield)
1059 free_fragment_message(plugin, fm);
1062 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1063 "Finished sending and got all acks for a fragmented message\n");
1066 check_next_fragment_timeout(plugin);
1067 check_fragment_queue(plugin);
1073 * Function to set the next fragment number
1074 * @param fm use this FragmentMessage
1078 set_next_message_fragment_pos(struct FragmentMessage * fm)
1081 //check if retransmit is needed
1082 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1085 // be positive and try again later :-D
1086 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1087 // find first missing fragment
1089 fm->message_pos = 0;
1092 //test if ack 0 (or X) was already received
1093 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1101 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1102 struct Radiotap_Send * header)
1105 if (session != NULL)
1107 header->rate = session->rate;
1108 header->tx_power = session->tx_power;
1109 header->antenna = session->antenna;
1114 header->tx_power = 0;
1115 header->antenna = 0;
1123 * function to generate the wlan hardware header for one packet
1124 * @param Header address to write the header to
1125 * @param to_mac_addr address of the recipient
1126 * @param plugin pointer to the plugin struct
1127 * @return GNUNET_YES if there was no error
1130 getWlanHeader(struct ieee80211_frame * Header,
1131 const struct MacAddress * to_mac_addr,
1132 struct Plugin * plugin)
1134 Header->i_fc[0] = 0x80;
1135 Header->i_fc[1] = 0x00;
1136 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1137 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1138 memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1145 * @param msgbuf pointer tor the data
1146 * @param msgbuf_size size of the data
1148 * @return 32bit crc value
1152 getcrc32(const char *msgbuf, size_t msgbuf_size)
1154 //TODO calc some crc
1161 * @param msgbuf pointer tor the data
1162 * @param msgbuf_size size of the data
1164 * @return 16bit crc value
1168 getcrc16(const char *msgbuf, size_t msgbuf_size)
1170 //TODO calc some crc
1176 send_hello_beacon(struct Plugin * plugin)
1180 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1185 struct GNUNET_MessageHeader * msgheader;
1186 struct ieee80211_frame * ieeewlanheader;
1187 struct Radiotap_Send * radioHeader;
1188 struct GNUNET_MessageHeader * msgheader2;
1190 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1191 *(plugin->env->our_hello)) <= WLAN_MTU);
1192 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1193 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1194 + GNUNET_HELLO_size(*(plugin->env->our_hello));
1196 msgheader = GNUNET_malloc(size);
1197 msgheader->size = htons(size);
1198 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1200 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1201 getRadiotapHeader(plugin, NULL, radioHeader);
1202 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1203 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin);
1205 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1206 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1207 + sizeof(struct GNUNET_MessageHeader));
1209 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1210 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1211 *(plugin->env->our_hello)));
1213 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1215 if (bytes == GNUNET_SYSERR)
1217 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1218 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1219 errno, strerror(errno));
1222 GNUNET_assert(bytes != GNUNET_SYSERR);
1223 GNUNET_assert(bytes == size);
1224 GNUNET_free(msgheader);
1226 set_next_beacon_time(plugin);
1227 check_next_fragment_timeout(plugin);
1231 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1236 struct GNUNET_MessageHeader * msgheader;
1237 struct ieee80211_frame * ieeewlanheader;
1238 struct Radiotap_Send * radioHeader;
1239 struct FragmentationAckHeader * msgheader2;
1241 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1243 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1244 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1247 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1248 "Sending ack for message_id %u with fragment field %u, size %u\n",
1249 ack->message_id, ack->fragments_field, size
1250 - sizeof(struct Radiotap_Send));
1253 msgheader = GNUNET_malloc(size);
1254 msgheader->size = htons(size);
1255 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1257 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1258 getRadiotapHeader(plugin, ack->session, radioHeader);
1259 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1260 getWlanHeader(ieeewlanheader, &ack->session->addr, plugin);
1262 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1263 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1264 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1265 msgheader2->message_id = htonl(ack->message_id);
1266 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1268 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1269 if (bytes == GNUNET_SYSERR)
1271 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1272 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1273 errno, strerror(errno));
1276 GNUNET_assert(bytes != GNUNET_SYSERR);
1277 GNUNET_assert(bytes == size);
1278 GNUNET_free(msgheader);
1279 check_next_fragment_timeout(plugin);
1283 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1285 struct Finish_send * finish;
1286 struct Plugin * plugin;
1290 plugin = finish->plugin;
1292 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1294 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1295 finish->msgheader, finish->size);
1296 GNUNET_assert(bytes != GNUNET_SYSERR);
1298 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1299 if (bytes != finish->size)
1302 finish->msgheader = finish->msgheader + bytes;
1303 finish->size = finish->size - bytes;
1304 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1305 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1306 &finish_sending, finish);
1310 GNUNET_free(finish->msgstart);
1311 GNUNET_free(finish);
1312 check_next_fragment_timeout(plugin);
1320 * Function called when wlan helper is ready to get some data
1322 * @param cls closure
1323 * @param tc GNUNET_SCHEDULER_TaskContext
1326 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1329 struct Plugin * plugin = cls;
1330 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1332 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1335 struct Session * session = NULL;
1336 struct FragmentMessage * fm = NULL;
1337 struct ieee80211_frame * ieeewlanheader = NULL;
1338 struct Radiotap_Send * radioHeader = NULL;
1339 struct GNUNET_MessageHeader * msgheader = NULL;
1341 struct FragmentationHeader fragheader;
1342 struct FragmentationHeader * fragheaderptr = NULL;
1343 struct Finish_send * finish = NULL;
1344 struct AckSendQueue * ack;
1347 const char * copystart = NULL;
1348 uint16_t copysize = 0;
1349 uint copyoffset = 0;
1351 if (plugin->ack_send_queue_head != NULL)
1353 ack = plugin->ack_send_queue_head;
1354 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1355 plugin->ack_send_queue_tail, ack);
1356 send_ack(plugin, ack);
1361 //test if a "hello-beacon" has to be send
1362 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1364 send_hello_beacon(plugin);
1370 fm = plugin->pending_Fragment_Messages_head;
1373 session = fm->session;
1374 GNUNET_assert(session != NULL);
1376 // test if message timed out
1377 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1380 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1383 check_fragment_queue(plugin);
1384 free_fragment_message(plugin, fm);
1390 //if (fm->message_size > WLAN_MTU)
1392 size = sizeof(struct FragmentationHeader);
1394 set_next_message_fragment_pos(fm);
1396 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1401 fragheader.fragment_off_or_num = htons(fm->message_pos);
1402 fragheader.message_id = htonl(fm->message_id_out);
1403 copystart = fm->msg + copyoffset;
1404 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1405 WLAN_MTU - sizeof(struct FragmentationHeader));
1409 GNUNET_ERROR_TYPE_DEBUG,
1410 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1411 fm->message_id_out, fm->message_pos, copysize
1412 + sizeof(struct FragmentationHeader), copyoffset,
1413 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1416 if (copyoffset >= fm->message_size)
1419 GNUNET_ERROR_TYPE_ERROR,
1420 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1421 copyoffset, fm->message_size, WLAN_MTU
1422 - sizeof(struct FragmentationHeader), copysize,
1425 GNUNET_assert(copyoffset < fm->message_size);
1426 //FIXME remove later
1427 GNUNET_assert(copystart < fm->msg + fm->message_size);
1429 fragheader.header.size = htons(copysize
1430 + sizeof(struct FragmentationHeader));
1431 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1436 // there is no need to split
1437 copystart = fm->msg;
1438 copysize = fm->message_size;
1442 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1443 + sizeof(struct GNUNET_MessageHeader);
1444 msgheader = GNUNET_malloc(size);
1445 msgheader->size = htons(size);
1446 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1448 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1449 getRadiotapHeader(plugin, session, radioHeader);
1451 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1452 getWlanHeader(ieeewlanheader, &fm->session->addr, plugin);
1454 //could be faster if content is just send and not copyed before
1455 //fragmentheader is needed
1456 //if (fm->message_size > WLAN_MTU)
1458 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1459 memcpy(&ieeewlanheader[1], &fragheader,
1460 sizeof(struct FragmentationHeader));
1461 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1462 memcpy(&fragheaderptr[1], copystart, copysize);
1466 memcpy(&ieeewlanheader[1], copystart, copysize);
1469 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1471 if (bytes == GNUNET_SYSERR)
1474 GNUNET_ERROR_TYPE_ERROR,
1475 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1476 errno, strerror(errno));
1479 GNUNET_assert(bytes != GNUNET_SYSERR);
1483 finish = GNUNET_malloc(sizeof( struct Finish_send));
1484 finish->plugin = plugin;
1485 finish->msgheader = (char *) msgheader + bytes;
1486 finish->size = size - bytes;
1487 finish->msgstart = msgheader;
1489 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1491 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1492 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1493 &finish_sending, finish);
1498 GNUNET_assert(bytes == size);
1500 GNUNET_free(msgheader);
1501 check_next_fragment_timeout(plugin);
1504 //check if this was the last fragment of this message, if true then queue at the end of the list
1505 if (copysize + copyoffset >= fm->message_size)
1507 GNUNET_assert(copysize + copyoffset == fm->message_size);
1509 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1510 plugin->pending_Fragment_Messages_tail, fm);
1512 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1513 plugin->pending_Fragment_Messages_tail, fm);
1514 // if fragments have opimized timeouts
1515 //sort_fragment_into_queue(plugin,fm);
1522 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1523 "do_transmit did nothing, should not happen!\n");
1528 * Another peer has suggested an address for this
1529 * peer and transport plugin. Check that this could be a valid
1530 * address. If so, consider adding it to the list
1533 * @param cls closure
1534 * @param addr pointer to the address
1535 * @param addrlen length of addr
1536 * @return GNUNET_OK if this is a plausible address for this peer
1540 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1542 //struct Plugin *plugin = cls;
1544 /* check if the address is plausible; if so,
1545 add it to our list! */
1547 GNUNET_assert(cls !=NULL);
1548 //FIXME mitm is not checked
1549 //Mac Address has 6 bytes
1552 /* TODO check for bad addresses like multicast, broadcast, etc */
1556 return GNUNET_SYSERR;
1562 * Function that can be used by the transport service to transmit
1563 * a message using the plugin.
1565 * @param cls closure
1566 * @param target who should receive this message
1567 * @param priority how important is the message
1568 * @param msgbuf the message to transmit
1569 * @param msgbuf_size number of bytes in 'msgbuf'
1570 * @param timeout when should we time out
1571 * @param session which session must be used (or NULL for "any")
1572 * @param addr the address to use (can be NULL if the plugin
1573 * is "on its own" (i.e. re-use existing TCP connection))
1574 * @param addrlen length of the address in bytes
1575 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1576 * otherwise the plugin may use other addresses or
1577 * existing connections (if available)
1578 * @param cont continuation to call once the message has
1579 * been transmitted (or if the transport is ready
1580 * for the next transmission call; or if the
1581 * peer disconnected...)
1582 * @param cont_cls closure for cont
1583 * @return number of bytes used (on the physical network, with overheads);
1584 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1585 * and does NOT mean that the message was not transmitted (DV)
1588 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1589 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1590 struct GNUNET_TIME_Relative timeout, struct Session *session,
1591 const void *addr, size_t addrlen, int force_address,
1592 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1594 struct Plugin * plugin = cls;
1595 struct PendingMessage * newmsg = NULL;
1596 struct WlanHeader * wlanheader = NULL;
1598 //check if msglen > 0
1599 GNUNET_assert(msgbuf_size > 0);
1601 //get session if needed
1602 if (session == NULL)
1604 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1606 session = get_Session(plugin, addr);
1610 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1611 _("Wlan Address len %d is wrong\n"), addrlen);
1616 //TODO target "problem" not solved
1617 //if (session->target != NULL){
1618 // GNUNET_assert(session->target == *target);
1620 session->target = *target;
1626 //queue message in session
1627 //test if there is no other message in the "queue"
1628 //FIXME: to many send requests
1629 //GNUNET_assert (session->pending_message == NULL);
1630 if (session->pending_message != NULL)
1632 newmsg = session->pending_message;
1634 GNUNET_ERROR_TYPE_ERROR,
1635 "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages %u\n",
1636 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1637 session->fragment_messages_out_count);
1638 if (session->pending_message2 != NULL)
1641 GNUNET_ERROR_TYPE_ERROR,
1642 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1647 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1648 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1649 wlanheader = (struct WlanHeader *) newmsg->msg;
1650 //copy msg to buffer, not fragmented / segmented yet, but with message header
1651 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1652 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1653 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1654 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1655 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1656 newmsg->transmit_cont = cont;
1657 newmsg->transmit_cont_cls = cont_cls;
1658 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1660 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1662 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1664 if (session->pending_message == NULL)
1666 session->pending_message = newmsg;
1670 session->pending_message2 = newmsg;
1674 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1675 "New message for %p with size (incl wlan header) %u added\n", session,
1676 newmsg->message_size);
1680 queue_Session(plugin, session);
1682 check_fragment_queue(plugin);
1683 //FIXME not the correct size
1689 * function to get the first message in the fragement queue (out) of a session
1690 * @param session pointer to the session
1691 * @return pointer to the struct FragmentMessage
1693 static struct FragmentMessage *
1694 get_fragment_message_from_session(struct Session * session)
1696 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1699 if (fm->session == session)
1709 * function to get the message in the fragement queue (out) of a session with a specific id
1710 * @param session pointer to the session
1711 * @param message_id id of the message
1712 * @return pointer to the struct FragmentMessage
1714 static struct FragmentMessage *
1715 get_fragment_message_from_session_and_id(struct Session * session,
1716 uint32_t message_id)
1718 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1721 if ((fm->session == session) && (fm->message_id_out == message_id))
1732 * function to get the receive message of a session
1733 * @param plugin pointer to the plugin struct
1734 * @param session session this fragment belongs to
1736 struct Receive_Message_Queue *
1737 get_receive_message_from_session(struct Plugin * plugin,
1738 struct Session * session)
1740 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1741 while (rec_message != NULL)
1743 if (rec_message->session == session)
1747 rec_message = rec_message->next;
1754 * Function to dispose the fragments received for a message and the message
1755 * @param plugin pointer to the plugin struct
1756 * @param rec_message pointer to the struct holding the message which should be freed
1759 free_receive_message(struct Plugin* plugin,
1760 struct Receive_Message_Queue * rx_message)
1762 GNUNET_assert(rx_message !=NULL);
1763 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1764 struct Receive_Fragment_Queue * rec_queue2;
1766 while (rec_queue != NULL)
1768 rec_queue2 = rec_queue;
1769 rec_queue = rec_queue->next;
1770 GNUNET_free(rec_queue2);
1773 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
1775 GNUNET_assert(plugin->pending_receive_messages > 0);
1776 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
1778 plugin->pending_receive_messages--;
1779 rx_message->session->fragment_messages_in_count--;
1780 GNUNET_free(rx_message);
1785 * Function that can be used to force the plugin to disconnect
1786 * from the given peer and cancel all previous transmissions
1787 * (and their continuation).
1789 * @param cls closure
1790 * @param target peer from which to disconnect
1793 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1795 struct Plugin *plugin = cls;
1796 struct Sessionqueue * queue = plugin->sessions;
1797 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1798 struct PendingMessage * pm = NULL;
1799 struct FragmentMessage * fm;
1800 struct Receive_Message_Queue * receive_queue;
1802 // just look at all the session for the needed one
1803 while (queue != NULL)
1805 // content is never NULL
1806 GNUNET_assert (queue->content != NULL);
1807 if (memcmp(target, &(queue->content->target),
1808 sizeof(struct GNUNET_PeerIdentity)) == 0)
1811 //is this session pending for send
1812 while (pendingsession != NULL)
1814 if (pendingsession->content == queue->content)
1816 plugin->pendingsessions--;
1817 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1818 plugin->pending_Sessions_tail, pendingsession);
1819 GNUNET_free(pendingsession);
1822 pendingsession = pendingsession->next;
1825 //is something of this session in the fragment queue?
1826 fm = get_fragment_message_from_session(queue->content);
1829 free_fragment_message(plugin, fm);
1830 fm = get_fragment_message_from_session(queue->content);
1832 check_next_fragment_timeout(plugin);
1834 //dispose all received fragments
1835 receive_queue = get_receive_message_from_session(plugin,
1837 while (receive_queue != NULL)
1839 free_receive_message(plugin, receive_queue);
1840 receive_queue = get_receive_message_from_session(plugin,
1844 // remove PendingMessage
1845 pm = queue->content->pending_message;
1848 GNUNET_free_non_null(pm->msg);
1852 GNUNET_free(queue->content);
1853 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1855 plugin->session_count--;
1860 queue = queue->next;
1865 * Convert the transports address to a nice, human-readable
1868 * @param cls closure
1869 * @param type name of the transport that generated the address
1870 * @param addr one of the addresses of the host, NULL for the last address
1871 * the specific address format depends on the transport
1872 * @param addrlen length of the address
1873 * @param numeric should (IP) addresses be displayed in numeric form?
1874 * @param timeout after how long should we give up?
1875 * @param asc function to call on each string
1876 * @param asc_cls closure for asc
1879 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1880 const void *addr, size_t addrlen, int numeric,
1881 struct GNUNET_TIME_Relative timeout,
1882 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1885 const unsigned char * input;
1887 //GNUNET_assert(cls !=NULL);
1890 /* invalid address (MAC addresses have 6 bytes) */
1895 input = (const unsigned char*) addr;
1896 GNUNET_snprintf(ret, sizeof(ret),
1897 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1898 input[0], input[1], input[2], input[3], input[4], input[5]);
1905 * Function called for a quick conversion of the binary address to
1906 * a numeric address. Note that the caller must not free the
1907 * address and that the next call to this function is allowed
1908 * to override the address again.
1910 * @param cls closure
1911 * @param addr binary address
1912 * @param addrlen length of the address
1913 * @return string representing the same address
1916 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
1918 static char ret[40];
1919 const struct MacAddress *mac;
1921 if (addrlen != sizeof(struct MacAddress))
1927 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
1928 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
1929 mac->mac[4], mac->mac[5]);
1934 * function to check if bitfield is representation of fragments of the message
1935 * @param rec_message message to check
1939 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
1941 uint64_t checkfragments = 0;
1942 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
1944 while (rec_queue != NULL)
1946 setBit((char*) &checkfragments, rec_queue->num);
1947 rec_queue = rec_queue->next;
1950 GNUNET_assert(checkfragments == rec_message->received_fragments);
1954 * Function to test if fragment number already exists in the fragments received
1956 * @param rec_message message this fragment belongs to
1957 * @param fh Fragmentheader of the fragment
1958 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
1962 is_double_msg(struct Receive_Message_Queue * rec_message,
1963 struct FragmentationHeader * fh)
1965 //test if bitfield is okay
1967 check_message_fragment_bitfield(rec_message);
1970 return testBit((char *) &rec_message->received_fragments, ntohs(
1971 fh->fragment_off_or_num));
1976 * Function to insert a fragment in a queue of a message
1977 * @param session session the fragment belongs to
1978 * @param rec_queue fragment to add
1982 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
1983 struct Receive_Fragment_Queue * rx_frag)
1985 GNUNET_assert(rx_message != NULL);
1986 GNUNET_assert(rx_frag != NULL);
1988 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
1989 struct WlanHeader * wlanheader = NULL;
1992 //this is the first fragment of the message (fragment id 0)
1993 if (rx_frag->num == 0)
1995 wlanheader = (struct WlanHeader *) rx_frag->msg;
1996 rx_message->rec_size = ntohs(wlanheader->header.size);
2000 while (rx_frag2 != NULL)
2002 if (rx_frag2->num > rx_frag->num)
2004 //next element number is grater than the current num
2005 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2006 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2009 rx_frag2 = rx_frag2->next;
2012 //no element has a grater number
2013 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2015 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2023 * handels the data after all fragments are put together
2025 * @param session_light
2026 * @param hdr pointer to the data
2029 wlan_data_massage_handler(struct Plugin * plugin,
2030 struct Session_light * session_light,
2031 const struct GNUNET_MessageHeader * hdr)
2033 struct WlanHeader * wlanheader = NULL;
2034 struct Session * session = NULL;
2035 const char * tempmsg = NULL;
2036 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2037 struct GNUNET_PeerIdentity tmptarget;
2039 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2044 GNUNET_ERROR_TYPE_DEBUG,
2045 "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2049 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2050 + sizeof(struct GNUNET_MessageHeader))
2052 //packet not big enought
2056 GNUNET_assert(session_light != NULL);
2057 if (session_light->session == NULL)
2059 session_light->session = search_session(plugin, &session_light->addr);
2061 session = session_light->session;
2062 wlanheader = (struct WlanHeader *) hdr;
2064 tempmsg = (char*) &wlanheader[1];
2065 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2067 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2070 //wrong crc, dispose message
2071 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2072 "Wlan message Header crc was wrong\n");
2076 //if not in session list
2077 if (session == NULL)
2081 GNUNET_ERROR_TYPE_DEBUG,
2082 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2083 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2084 sizeof(struct WlanHeader));
2086 //try if it is a hello message
2087 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2088 + sizeof(struct WlanHeader))
2090 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2092 if (GNUNET_HELLO_get_id(
2093 (const struct GNUNET_HELLO_Message *) temp_hdr,
2094 &tmptarget) == GNUNET_OK)
2096 session = create_session(plugin, &session_light->addr);
2097 session_light->session = session;
2098 memcpy(&session->target, &tmptarget,
2099 sizeof(struct GNUNET_PeerIdentity));
2103 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2104 "WLAN client not in session list and hello message not okay\n");
2111 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2112 "WLAN client not in session list and not a hello message\n");
2119 GNUNET_ERROR_TYPE_WARNING,
2120 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2121 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2122 sizeof(struct WlanHeader));
2127 //"receive" the message
2130 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2131 (const char *) temp_hdr,
2132 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2138 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2139 "wlan_data_massage_handler got wrong message type\n");
2147 * Function to check if all fragments of a message have been received
2148 * @param plugin the plugin handle
2149 * @param session_light information of the message sender
2150 * @param session session the message belongs to
2151 * @param rec_message pointer to the message that should be checked
2155 check_rec_finished_msg(struct Plugin* plugin,
2156 struct Session_light * session_light, struct Session * session,
2157 struct Receive_Message_Queue * rx_message)
2159 GNUNET_assert(rx_message !=NULL);
2161 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2162 int packetsize = rx_message->rec_size;
2165 uint64_t bitfield = 0;
2168 //check if first fragment is present
2169 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2173 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2174 else if (packetsize < sizeof(struct WlanHeader)
2175 + sizeof(struct GNUNET_MessageHeader))
2178 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2180 free_receive_message(plugin, rx_message);
2185 check_message_fragment_bitfield(rx_message);
2188 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2190 bitfield = ~bitfield;
2191 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2192 if (rx_message->received_fragments == bitfield)
2195 while (rx_frag != NULL)
2197 sum += rx_frag->size;
2198 rx_frag = rx_frag->next;
2200 //sum should always be smaller or equal of
2201 GNUNET_assert(sum <= packetsize);
2202 if (sum == packetsize)
2206 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2207 "check_rec_finished_msg: A message for %p is complete\n", session);
2211 //copy fragments together
2212 msg = GNUNET_malloc(packetsize);
2213 rx_frag = rx_message->frag_head;
2215 while (rx_frag != NULL)
2217 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2218 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2219 aktnum += rx_frag->size;
2220 rx_frag = rx_frag->next;
2223 free_receive_message(plugin, rx_message);
2224 //call wlan_process_helper to process the message
2225 wlan_data_massage_handler(plugin, session_light,
2226 (struct GNUNET_MessageHeader*) msg);
2227 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2236 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2239 GNUNET_assert(client != NULL);
2240 GNUNET_assert(cls != NULL);
2241 struct Session * session = (struct Session *) client;
2242 struct Plugin * plugin = (struct Plugin *) cls;
2244 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2245 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2246 distance[0].value = htonl(1);
2247 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2248 distance[1].value = htonl(0);
2251 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2252 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2253 wlan_plugin_address_to_string(NULL, session->addr, 6), htons(hdr->size));
2256 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2257 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2258 (const char*) &session->addr, sizeof(session->addr));
2262 * function to add an ack to send it for a received fragment
2263 * @param plugin pointer to the global plugin structure
2264 * @param session pointer to the session this ack belongs to
2265 * @param bitfield bitfield to send
2266 * @param fh pointer to the fragmentation header which we would like to acknolage
2270 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2271 uint64_t bitfield, struct FragmentationHeader * fh)
2273 struct AckSendQueue * ack;
2275 GNUNET_assert(plugin != NULL);
2276 GNUNET_assert(session != NULL);
2277 GNUNET_assert(fh != NULL);
2279 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2280 ack->fragments_field = bitfield;
2281 ack->message_id = ntohl(fh->message_id);
2282 ack->session = session;
2284 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2285 plugin->ack_send_queue_tail, ack);
2290 * function to get the receive message from the message id and the session
2291 * @param plugin pointer to the plugin struct
2292 * @param session session this fragment belongs to
2293 * @param message_id id of the message
2296 struct Receive_Message_Queue *
2297 get_receive_message(struct Plugin * plugin, struct Session * session,
2298 uint32_t message_id)
2300 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2301 while (rec_message != NULL)
2303 if ((rec_message->message_id_in == message_id) && (rec_message->session
2308 rec_message = rec_message->next;
2316 * function to insert a received fragment into the right fragment queue of the right message
2317 * @param plugin pointer to the plugin struct
2318 * @param session_light pointer to the session_light struct of this message
2319 * @param session session this fragment belongs to
2320 * @param fh pointer to the header of the fragment
2321 * @return new fragment bitfield for the message
2325 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2326 struct Session_light * session_light, struct Session * session,
2327 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2329 struct Receive_Fragment_Queue * rx_frag = NULL;
2330 struct Receive_Message_Queue * rx_message;
2331 const char * tempmsg = (char*) &fh[1];
2332 uint64_t retval = 0;
2334 //TODO fragments do not timeout
2335 //check if message_id is right or it is a new msg
2336 GNUNET_assert(fh != NULL);
2338 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2340 if (rx_message == NULL)
2342 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2345 //new message incoming
2346 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2347 rx_message->message_id_in = ntohl(fh->message_id);
2348 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2349 rx_message->session = session;
2350 rx_message->timeout = GNUNET_TIME_absolute_add(
2351 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2352 rx_message->received_fragments = 0;
2354 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2356 session->fragment_messages_in_count++;
2357 plugin->pending_receive_messages++;
2361 GNUNET_ERROR_TYPE_DEBUG,
2362 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2363 rx_message->message_id_in, session->fragment_messages_in_count,
2364 plugin->pending_receive_messages);
2371 GNUNET_ERROR_TYPE_INFO,
2372 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2373 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2378 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2383 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2384 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2385 rx_frag->size = ntohs(fh->header.size)
2386 - sizeof(struct FragmentationHeader);
2387 rx_frag->num = ntohs(fh->fragment_off_or_num);
2388 rx_frag->msg = (char*) &(rx_frag[1]);
2389 //copy msg to buffer
2390 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2391 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2392 insert_fragment_in_queue(rx_message, rx_frag);
2394 retval = rx_message->received_fragments;
2398 GNUNET_ERROR_TYPE_DEBUG,
2399 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2400 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2401 rx_message->received_fragments, session);
2404 check_rec_finished_msg(plugin, session_light, session, rx_message);
2408 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2409 retval = rx_message->received_fragments;
2417 * Function used for to process the data received from the wlan interface
2419 * @param cls the plugin handle
2420 * @param session_light FIXME: document
2421 * @param hdr hdr of the GNUNET_MessageHeader
2424 wlan_data_helper(void *cls, struct Session_light * session_light,
2425 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2427 struct Plugin *plugin = cls;
2428 struct Session * session = NULL;
2430 struct FragmentationHeader * fh = NULL;
2431 struct FragmentationAckHeader * fah = NULL;
2432 struct FragmentMessage * fm = NULL;
2434 const char * tempmsg = NULL;
2436 uint64_t fragment_bitfield = 0;
2439 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2442 //TODO better DOS protection, error handling
2443 //TODO test first than create session
2444 GNUNET_assert(session_light != NULL);
2448 GNUNET_ERROR_TYPE_DEBUG,
2449 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2450 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2451 session_light->addr, 6));
2454 if (session_light->session == NULL)
2456 session_light->session = get_Session(plugin, &session_light->addr);
2458 GNUNET_assert(GNUNET_HELLO_get_id(
2459 (const struct GNUNET_HELLO_Message *) &hdr[1],
2460 &(session_light->session->target) ) != GNUNET_SYSERR);
2465 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2468 GNUNET_assert(session_light != NULL);
2469 if (session_light->session == NULL)
2471 session_light->session = search_session(plugin, &session_light->addr);
2473 session = session_light->session;
2475 fh = (struct FragmentationHeader *) hdr;
2476 tempmsg = (char*) &fh[1];
2480 GNUNET_ERROR_TYPE_DEBUG,
2481 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2482 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2483 hdr->size), wlan_plugin_address_to_string(NULL,
2484 session_light->addr, 6));
2487 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2489 //wrong crc, dispose message
2490 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2494 //if in the session list
2495 if (session != NULL)
2497 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2498 session_light, session, fh, rxinfo);
2504 GNUNET_ERROR_TYPE_INFO,
2505 "WLAN client not in session list, fragment num %u, message id %u\n",
2506 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2507 wlan_data_massage_handler(plugin, session_light,
2508 (struct GNUNET_MessageHeader *) tempmsg);
2509 session = session_light->session;
2510 //test if a session was created
2511 if (session == NULL)
2515 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2518 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2519 check_next_fragment_timeout(plugin);
2524 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2529 GNUNET_ERROR_TYPE_DEBUG,
2530 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2531 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2532 session_light->addr, 6));
2535 GNUNET_assert(session_light != NULL);
2536 if (session_light->session == NULL)
2538 session_light->session = search_session(plugin, &session_light->addr);
2539 GNUNET_assert(session_light->session != NULL);
2541 session = session_light->session;
2542 fah = (struct FragmentationAckHeader *) hdr;
2543 fm = get_fragment_message_from_session_and_id(session, ntohl(
2548 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(fah->fragment_field);
2549 check_finished_fragment(plugin, fm);
2553 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2554 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2564 GNUNET_ERROR_TYPE_INFO,
2565 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2566 ntohs(hdr->type), ntohs(hdr->size));
2572 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2573 "Helper finished\n");
2579 macprinter(const u_int8_t * mac)
2581 static char macstr[20];
2583 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2584 mac[2], mac[3], mac[4], mac[5]);
2589 * Function used for to process the data from the suid process
2591 * @param cls the plugin handle
2592 * @param client client that send the data (not used)
2593 * @param hdr header of the GNUNET_MessageHeader
2596 wlan_process_helper(void *cls, void *client,
2597 const struct GNUNET_MessageHeader *hdr)
2599 struct Plugin *plugin = cls;
2600 struct ieee80211_frame * wlanIeeeHeader = NULL;
2601 struct Session_light * session_light = NULL;
2602 struct Radiotap_rx * rxinfo;
2603 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2608 switch (ntohs(hdr->type))
2610 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2613 GNUNET_ERROR_TYPE_DEBUG,
2614 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2618 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2619 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2620 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2623 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2624 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2625 hdr->size), sizeof(struct ieee80211_frame)
2626 + sizeof(struct GNUNET_MessageHeader));
2629 /* FIXME: restart SUID process */
2632 rxinfo = (struct Radiotap_rx *) &hdr[1];
2633 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2635 //process only if it is an broadcast or for this computer both with the gnunet bssid
2638 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid, sizeof(struct MacAddress))
2641 //check for broadcast or mac
2642 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2643 sizeof(struct MacAddress) == 0) || memcmp(
2644 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2645 sizeof(struct MacAddress)) == 0)
2648 // process the inner data
2651 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2652 - sizeof(struct GNUNET_MessageHeader)
2653 - sizeof(struct Radiotap_rx);
2655 session_light = GNUNET_malloc(sizeof(struct Session_light));
2656 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2657 sizeof(struct MacAddress));
2658 //session_light->session = search_session(plugin,session_light->addr);
2661 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2662 while (pos < datasize)
2664 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2667 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2668 pos += ntohs(temp_hdr->size);
2673 GNUNET_free(session_light);
2678 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2679 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2680 wlanIeeeHeader->i_addr1));
2687 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2688 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2689 wlanIeeeHeader->i_addr2));
2693 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2694 //TODO more control messages
2695 //TODO use struct wlan_helper_control
2696 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2699 /* FIXME: restart SUID process */
2702 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2704 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2705 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2706 wlan_plugin_address_to_string(cls, &plugin->mac_address,
2707 sizeof(struct MacAddress)));
2709 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2710 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2719 * We have been notified that wlan-helper has written something to stdout.
2720 * Handle the output, then reschedule this function to be called again once
2721 * more is available.
2723 * @param cls the plugin handle
2724 * @param tc the scheduling context
2727 wlan_plugin_helper_read(void *cls,
2728 const struct GNUNET_SCHEDULER_TaskContext *tc)
2730 struct Plugin *plugin = cls;
2731 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2736 "Start reading from STDIN\n");
2739 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2742 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2745 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2750 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2751 _("Finished reading from wlan-helper stdout with code: %d\n"),
2756 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2757 GNUNET_NO, GNUNET_NO);
2759 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2760 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2761 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2762 &wlan_plugin_helper_read, plugin);
2766 * Start the gnunet-wlan-helper process.
2768 * @param plugin the transport plugin
2769 * @param testmode should we use the dummy driver for testing?
2770 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2773 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2775 const char * filename = "gnunet-transport-wlan-helper";
2776 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2777 if (plugin->server_stdout == NULL)
2778 return GNUNET_SYSERR;
2780 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2781 if (plugin->server_stdin == NULL)
2782 return GNUNET_SYSERR;
2785 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2786 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2787 plugin->interface, testmode);
2789 /* Start the server process */
2791 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2792 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2793 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2794 if (plugin->server_proc == NULL)
2797 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2798 "Failed to start gnunet-wlan-helper process\n");
2800 return GNUNET_SYSERR;
2803 /* Close the write end of the read pipe */
2804 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2806 /* Close the read end of the write pipe */
2807 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2809 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2810 GNUNET_DISK_PIPE_END_READ);
2811 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2812 GNUNET_DISK_PIPE_END_WRITE);
2814 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2817 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2818 "Adding server_read_task for the wlan-helper\n");
2821 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2822 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2823 &wlan_plugin_helper_read, plugin);
2829 * Exit point from the plugin.
2830 * @param cls pointer to the api struct
2835 libgnunet_plugin_transport_wlan_done(void *cls)
2837 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2838 struct Plugin *plugin = api->cls;
2841 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2842 "libgnunet_plugin_transport_wlan_done started\n");
2845 GNUNET_assert(cls !=NULL);
2847 if (plugin->suid_tokenizer != NULL)
2848 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2850 if (plugin->data_tokenizer != NULL)
2851 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
2853 GNUNET_free_non_null(plugin->interface);
2854 GNUNET_free (plugin);
2860 * Entry point for the plugin.
2862 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2863 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2866 libgnunet_plugin_transport_wlan_init(void *cls)
2868 //struct GNUNET_SERVICE_Context *service;
2869 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2870 struct GNUNET_TRANSPORT_PluginFunctions *api;
2871 struct Plugin *plugin;
2872 static unsigned long long testmode = 0;
2874 GNUNET_assert(cls !=NULL);
2876 plugin = GNUNET_malloc (sizeof (struct Plugin));
2878 plugin->pendingsessions = 0;
2879 plugin->session_count = 0;
2880 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2881 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2882 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2884 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
2887 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
2889 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2890 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2892 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2894 api->send = &wlan_plugin_send;
2895 api->disconnect = &wlan_plugin_disconnect;
2896 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2897 api->check_address = &wlan_plugin_address_suggested;
2898 api->address_to_string = &wlan_plugin_address_to_string;
2902 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2904 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
2905 "transport-wlan", "TESTMODE", &testmode))
2906 testmode = 0; //default value
2909 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
2911 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
2912 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
2914 libgnunet_plugin_transport_wlan_done(api);
2920 set_next_beacon_time(plugin);
2922 wlan_transport_start_wlan_helper(plugin, testmode);
2925 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
2931 /* end of plugin_transport_wlan.c */