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
64 #define DEBUG_wlan_retransmission GNUNET_NO
66 #define MESSAGE_LENGHT_UNKNOWN -1
67 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
70 * After how long do we expire an address that we
71 * learned from another peer if it is not reconfirmed
74 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
77 * Initial handshake message for a session.
82 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
84 struct GNUNET_MessageHeader header;
87 * Identit*mac_y of the node connecting (TCP client)
89 struct GNUNET_PeerIdentity clientIdentity;
94 * Encapsulation of all of the state of the plugin.
101 struct GNUNET_TRANSPORT_PluginEnvironment *env;
104 * List of open sessions. head
106 struct Sessionqueue *sessions;
109 * List of open sessions. tail
111 struct Sessionqueue *sessions_tail;
116 unsigned int session_count;
119 * encapsulation of data from the local wlan helper program
121 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
124 * encapsulation of packets received
126 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
129 * stdout pipe handle for the gnunet-wlan-helper process
131 struct GNUNET_DISK_PipeHandle *server_stdout;
134 * stdout file handle for the gnunet-wlan-helper process
136 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
139 * stdin pipe handle for the gnunet-wlan-helper process
141 struct GNUNET_DISK_PipeHandle *server_stdin;
144 * stdin file handle for the gnunet-wlan-helper process
146 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
149 * ID of the gnunet-wlan-server std read task
151 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
154 * ID of the gnunet-wlan-server std read task
156 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
159 * ID of the delay task for writing
161 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
164 * The process id of the wlan process
166 struct GNUNET_OS_Process *server_proc;
169 * The interface of the wlan card given to us by the user.
174 * The mac_address of the wlan card given to us by the helper.
176 struct MacAddress mac_address;
179 * Sessions currently pending for transmission
180 * to this peer, if any.
182 struct Sessionqueue * pending_Sessions;
185 * Sessions currently pending for transmission
186 * to this peer (tail), if any.
188 struct Sessionqueue * pending_Sessions_tail;
191 * number of pending sessions
193 unsigned int pendingsessions;
196 * Messages in the fragmentation queue, head
198 struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
201 * Messages in the in Queue, head
203 struct Receive_Message_Queue * receive_messages_head;
206 * Messages in the in Queue, tail
208 struct Receive_Message_Queue * receive_messages_teil;
211 * number of messages in the in queue
213 unsigned int pending_receive_messages;
216 * time of the next "hello-beacon"
218 struct GNUNET_TIME_Absolute beacon_time;
221 * queue to send acks for received fragments (head)
223 struct AckSendQueue * ack_send_queue_head;
226 * queue to send acks for received fragments (tail)
228 struct AckSendQueue * ack_send_queue_tail;
233 * Struct to store data if file write did not accept the whole packet
237 struct Plugin * plugin;
239 struct GNUNET_MessageHeader * msgstart;
241 struct GNUNET_TIME_Absolute next_send;
245 * Queue of sessions, for the general session queue and the pending session queue
250 struct Sessionqueue * next;
251 struct Sessionqueue * prev;
252 struct Session * content;
256 * Queue for the fragments received
258 struct Receive_Fragment_Queue
260 struct Receive_Fragment_Queue * next;
261 struct Receive_Fragment_Queue * prev;
265 struct Radiotap_rx rxinfo;
268 struct Session_id_pair
270 struct Session * session;
274 struct Plugin_Session_pair
276 struct Plugin * plugin;
277 struct Session * session;
281 * Queue for the fragments received
283 struct Receive_Message_Queue
285 struct Receive_Message_Queue * next;
287 struct Receive_Message_Queue * prev;
290 * current number for message incoming, to distinguish between the messages
292 uint32_t message_id_in;
295 * size of the message received,
296 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
297 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
302 * Sorted queue with the fragments received; head
305 struct Receive_Fragment_Queue * frag_head;
308 * Sorted queue with the fragments received; tail
311 struct Receive_Fragment_Queue * frag_tail;
314 * Session this fragment belongs to
317 struct Session * session;
320 * Timeout value for the pending message.
322 struct GNUNET_TIME_Absolute timeout;
325 * Bitfield of received fragments
328 uint64_t received_fragments;
332 * Information kept for each message that is yet to
335 struct PendingMessage
339 * The pending message
344 * Size of the message
349 * Continuation function to call once the message
350 * has been sent. Can be NULL if there is no
351 * continuation to call.
353 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
356 * Cls for transmit_cont
358 void * transmit_cont_cls;
361 * Timeout value for the pending message.
363 struct GNUNET_TIME_Absolute timeout;
368 * Queue for acks to send for fragments recived
374 struct AckSendQueue * next;
375 struct AckSendQueue * prev;
377 struct Session * session;
379 * ID of message, to distinguish between the messages, picked randomly.
384 * Bit field for received fragments
386 uint64_t fragments_field;
391 * Session infos gathered from a messages
397 * the session this message belongs to
399 struct Session * session;
403 struct MacAddress addr;
407 * Session handle for connections.
415 struct SessionHeader header;
418 * Pointer to the global plugin struct.
420 struct Plugin *plugin;
423 * Message currently pending for transmission
424 * to this peer, if any.
426 struct PendingMessage *pending_message;
429 * Message currently pending for transmission
430 * to this peer, if any.
432 struct PendingMessage *pending_message2;
435 * To whom are we talking to (set to our identity
436 * if we are still waiting for the welcome message)
438 struct GNUNET_PeerIdentity target;
443 struct MacAddress addr;
446 * Address of the other peer (either based on our 'connect'
447 * call or on our 'accept' call).
452 * Last activity on this connection. Used to select preferred
455 struct GNUNET_TIME_Absolute last_activity;
458 * count of messages in the fragment out queue for this session
461 int fragment_messages_out_count;
464 * count of messages in the fragment in queue for this session
467 int fragment_messages_in_count;
477 * Struct for Messages in the fragment queue
480 struct FragmentMessage
483 * heap pointer of this message
485 struct GNUNET_CONTAINER_HeapNode * node;
488 * Session this message belongs to
491 struct Session *session;
494 * This is a doubly-linked list.
496 struct FragmentMessage *next;
499 * This is a doubly-linked list.
501 struct FragmentMessage *prev;
504 * The pending message
509 * 0 if not in ack queue
516 * Timeout value for the pending message.
518 struct GNUNET_TIME_Absolute timeout;
521 * Timeout value for the pending fragments.
522 * Stores the time when the next msg fragment ack has to be received
524 struct GNUNET_TIME_Absolute next_ack;
527 * bitfield with all acks received for this message
529 uint64_t ack_bitfield;
532 * Size of the message
537 * pos / next fragment number in the message, for fragmentation/segmentation,
538 * some acks can be missing but there is still time
540 uint32_t message_pos;
543 * current number for message outgoing, to distinguish between the messages
545 uint32_t message_id_out;
549 * Header for messages which need fragmentation
551 struct FragmentationAckHeader
554 struct GNUNET_MessageHeader header;
557 * ID of message, to distinguish between the messages, picked randomly.
559 uint32_t message_id GNUNET_PACKED;
562 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
564 uint64_t fragment_field GNUNET_PACKED;
568 static struct FragmentMessage * return_val;
571 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
574 * Sets a bit active in the bitArray. Increment bit-specific
575 * usage counter on disk only if below 4bit max (==15).
577 * @param bitArray memory area to set the bit in
578 * @param bitIdx which bit to set
581 setBit(char *bitArray, unsigned int bitIdx)
584 unsigned int targetBit;
586 arraySlot = bitIdx / 8;
587 targetBit = (1L << (bitIdx % 8));
588 bitArray[arraySlot] |= targetBit;
592 * Checks if a bit is active in the bitArray
594 * @param bitArray memory area to set the bit in
595 * @param bitIdx which bit to test
596 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
599 testBit(char *bitArray, unsigned int bitIdx)
602 unsigned int targetBit;
605 targetBit = (1L << (bitIdx % 8));
606 if (bitArray[slot] & targetBit)
612 * get the next message number, at the moment just a random one
613 * @return returns the next valid message-number for sending packets
616 get_next_message_id()
618 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
622 * search for a session with the addr
624 * @param plugin pointer to the plugin struct
625 * @param addr pointer to the mac address of the peer
626 * @return returns the session
628 static struct Session *
629 search_session(struct Plugin *plugin, const struct MacAddress *addr)
631 struct Sessionqueue * queue = plugin->sessions;
633 while (queue != NULL)
635 GNUNET_assert (queue->content != NULL);
636 if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
637 return queue->content; /* session found */
644 * Function called for a quick conversion of the binary address to
645 * a numeric address. Note that the caller must not free the
646 * address and that the next call to this function is allowed
647 * to override the address again.
650 * @param addr binary address
651 * @param addrlen length of the address
652 * @return string representing the same address
655 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
658 const struct MacAddress *mac;
660 if (addrlen != sizeof(struct MacAddress))
666 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
667 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
668 mac->mac[4], mac->mac[5]);
673 * create a new session
675 * @param plugin pointer to the plugin struct
676 * @param addr pointer to the mac address of the peer
677 * @return returns the session
680 static struct Session *
681 create_session(struct Plugin *plugin, const struct MacAddress * addr)
683 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
685 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
687 queue->content = GNUNET_malloc (sizeof (struct Session));
688 queue->content->plugin = plugin;
689 queue->content->addr = *addr;
690 queue->content->fragment_messages_out_count = 0;
691 queue->content->fragment_messages_in_count = 0;
693 plugin->session_count++;
696 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
697 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
700 return queue->content;
704 * Get session from address, create if no session exists
706 * @param plugin pointer to the plugin struct
707 * @param addr pointer to the mac address of the peer
708 * @return returns the session
710 static struct Session *
711 get_session(struct Plugin *plugin, const struct MacAddress *addr)
713 struct Session * session = search_session(plugin, addr);
716 return create_session(plugin, addr);
720 * Queue the session to send data
721 * checks if there is a message pending
722 * checks if this session is not allready in the queue
723 * @param plugin pointer to the plugin
724 * @param session pointer to the session to add
727 queue_session(struct Plugin *plugin, struct Session * session)
729 struct Sessionqueue * queue = plugin->pending_Sessions;
730 struct Sessionqueue * lastitem = NULL;
732 if (session->pending_message != NULL)
734 while (queue != NULL)
736 // content is never NULL
737 GNUNET_assert (queue->content != NULL);
738 // is session already in queue?
739 if (session == queue->content)
748 // Session is not in the queue
750 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
751 queue->content = session;
754 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions,
755 plugin->pending_Sessions_tail, queue);
756 plugin->pendingsessions++;
763 * Function to schedule the write task, executed after a delay
766 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
768 struct Plugin * plugin = cls;
769 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
771 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
774 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
775 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
777 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
778 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
779 &do_transmit, plugin);
785 * Function to calculate the time of the next periodic "hello-beacon"
788 set_next_beacon_time(struct Plugin * const plugin)
790 //under 10 known peers: once a second
791 if (plugin->session_count < 10)
793 plugin->beacon_time = GNUNET_TIME_absolute_add(
794 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
795 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
797 //under 30 known peers: every 10 seconds
798 else if (plugin->session_count < 30)
800 plugin->beacon_time = GNUNET_TIME_absolute_add(
801 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
802 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
804 //over 30 known peers: once a minute
807 plugin->beacon_time = GNUNET_TIME_absolute_add(
808 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
809 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
814 static struct GNUNET_TIME_Relative
815 get_next_frag_timeout(struct FragmentMessage * fm)
817 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
818 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
823 * Function to get the timeout value for acks for this session
826 static struct GNUNET_TIME_Relative
827 get_ack_timeout(struct FragmentMessage * fm)
829 return FRAGMENT_TIMEOUT;
833 * Function to set the timer for the next timeout of the fragment queue
834 * @param plugin the handle to the plugin struct
838 set_next_send(struct Plugin * const plugin)
840 struct FragmentMessage * fm;
841 struct GNUNET_TIME_Relative next_send = GNUNET_TIME_UNIT_FOREVER_REL;
844 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
846 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
847 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
850 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
852 //check if some acks are in the queue
853 if (plugin->ack_send_queue_head != NULL)
855 next_send = GNUNET_TIME_UNIT_ZERO;
858 //check if there are some fragments in the queue
861 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
864 if (GNUNET_CONTAINER_node_get_cost(fm->node) != 0)
866 next_send = GNUNET_TIME_relative_min(next_send,
867 get_next_frag_timeout(fm));
871 next_send = GNUNET_TIME_UNIT_ZERO;
878 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
879 next_send.rel_value);
883 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
884 &delay_fragment_task, plugin);
889 * Function to get the next queued Session, removes the session from the queue
890 * @param plugin pointer to the plugin struct
891 * @return pointer to the session found, returns NULL if there is now session in the queue
893 static struct Session *
894 get_next_queue_session(struct Plugin * plugin)
896 struct Session * session;
897 struct Sessionqueue * sessionqueue;
898 struct Sessionqueue * sessionqueue_alt;
899 struct PendingMessage * pm;
900 sessionqueue = plugin->pending_Sessions;
901 while (sessionqueue != NULL)
903 session = sessionqueue->content;
905 pm = session->pending_message;
910 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
911 "pending message is empty, should not happen. session %p\n",
915 GNUNET_assert(pm != NULL);
917 //check for message timeout
918 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
920 //check if session has no message in the fragment queue
921 if (session->fragment_messages_out_count
922 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
924 plugin->pendingsessions--;
925 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
926 plugin->pending_Sessions_tail, sessionqueue);
927 GNUNET_free(sessionqueue);
933 sessionqueue = sessionqueue->next;
939 session->pending_message = session->pending_message2;
940 session->pending_message2 = NULL;
942 //call the cont func that it did not work
943 if (pm->transmit_cont != NULL)
944 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
946 GNUNET_free(pm->msg);
949 if (session->pending_message == NULL)
951 sessionqueue_alt = sessionqueue;
952 sessionqueue = sessionqueue->next;
953 plugin->pendingsessions--;
954 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
955 plugin->pending_Sessions_tail, sessionqueue_alt);
957 GNUNET_free(sessionqueue_alt);
967 * frees the space of a message in the fragment queue (send queue)
968 * @param plugin the plugin struct
969 * @param fm message to free
972 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
974 struct Session * session = fm->session;
978 (session->fragment_messages_out_count)--;
979 GNUNET_free_non_null(fm->msg);
980 GNUNET_CONTAINER_heap_remove_node(fm->node);
983 queue_session(plugin, session);
985 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
986 "free pending fragment messages, pending messages remaining %u\n",
987 GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
993 * Function to check if there is some space in the fragment queue
994 * inserts a message if space is available
995 * @param plugin the plugin struct
999 check_fragment_queue(struct Plugin * plugin)
1001 struct Session * session;
1002 struct FragmentMessage * fm;
1003 struct GNUNET_PeerIdentity pid;
1005 struct PendingMessage * pm;
1007 if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1008 < FRAGMENT_QUEUE_SIZE)
1010 session = get_next_queue_session(plugin);
1011 if (session != NULL)
1013 pm = session->pending_message;
1014 session->pending_message = NULL;
1015 session->fragment_messages_out_count++;
1016 GNUNET_assert(pm != NULL);
1018 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1019 fm->message_size = pm->message_size;
1021 fm->session = session;
1022 fm->timeout.abs_value = pm->timeout.abs_value;
1023 fm->message_pos = 0;
1024 fm->next_ack = GNUNET_TIME_absolute_get();
1025 fm->message_id_out = get_next_message_id();
1026 fm->ack_bitfield = 0;
1027 fm->node = GNUNET_CONTAINER_heap_insert(
1028 plugin->pending_Fragment_Messages, fm, 0);
1030 if (pm->transmit_cont != NULL)
1032 pid = session->target;
1033 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1035 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1036 "called pm->transmit_cont for %p\n", session);
1042 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1043 "no pm->transmit_cont for %p\n", session);
1048 if (session->pending_message2 != NULL)
1050 session->pending_message = session->pending_message2;
1051 session->pending_message2 = NULL;
1053 queue_session(plugin, session);
1059 //check if timeout changed
1060 set_next_send(plugin);
1064 * Funktion to check if all fragments where send and the acks received
1065 * frees the space if finished
1066 * @param plugin the plugin struct
1067 * @param fm the message to check
1070 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1072 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1073 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1074 - sizeof(struct FragmentationHeader)));
1075 uint64_t tmpfield = UINT64_MAX;
1076 tmpfield = tmpfield >> maxack;
1080 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1081 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1082 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1085 if (fm->ack_bitfield == tmpfield)
1088 #if DEBUG_wlan_retransmission
1089 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1090 "Finished sending and got all acks; message_id %u\n",
1091 fm->message_id_out);
1094 free_fragment_message(plugin, fm);
1098 check_fragment_queue(plugin);
1104 * Function to set the next fragment number
1105 * @param fm use this FragmentMessage
1109 set_next_message_fragment_pos(struct Plugin * plugin,
1110 struct FragmentMessage * fm)
1115 //check if retransmit is needed
1116 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1119 // be positive and try again later :-D
1120 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1121 // find first missing fragment
1123 fm->message_pos = 0;
1125 GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1128 #if DEBUG_wlan_retransmission
1129 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1130 "Retransmit; message_id %u; fragment number %i, size: %u\n",
1131 fm->message_id_out, fm->message_pos, fm->message_size);
1135 //test if ack 0 (or X) was already received
1136 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1144 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1145 struct Radiotap_Send * header)
1148 if (session != NULL)
1150 header->rate = session->rate;
1151 header->tx_power = session->tx_power;
1152 header->antenna = session->antenna;
1157 header->tx_power = 0;
1158 header->antenna = 0;
1165 * function to generate the wlan hardware header for one packet
1166 * @param Header address to write the header to
1167 * @param to_mac_addr address of the recipient
1168 * @param plugin pointer to the plugin struct
1169 * @return GNUNET_YES if there was no error
1172 getWlanHeader(struct ieee80211_frame * Header,
1173 const struct MacAddress * to_mac_addr, struct Plugin * plugin)
1175 Header->i_fc[0] = 0x80;
1176 Header->i_fc[1] = 0x00;
1177 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1178 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1179 memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1186 * @param msgbuf pointer tor the data
1187 * @param msgbuf_size size of the data
1189 * @return 32bit crc value
1193 getcrc32(const char *msgbuf, size_t msgbuf_size)
1195 //TODO calc some crc
1202 * @param msgbuf pointer tor the data
1203 * @param msgbuf_size size of the data
1205 * @return 16bit crc value
1209 getcrc16(const char *msgbuf, size_t msgbuf_size)
1211 //TODO calc some crc
1216 send_hello_beacon(struct Plugin * plugin)
1220 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1225 uint16_t hallo_size;
1226 struct GNUNET_MessageHeader * msgheader;
1227 struct ieee80211_frame * ieeewlanheader;
1228 struct Radiotap_Send * radioHeader;
1229 struct GNUNET_MessageHeader * msgheader2;
1231 hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1232 GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1233 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1234 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1237 msgheader = GNUNET_malloc(size);
1238 msgheader->size = htons(size);
1239 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1241 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1242 getRadiotapHeader(plugin, NULL, radioHeader);
1243 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1244 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin);
1246 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1247 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1248 + sizeof(struct GNUNET_MessageHeader));
1250 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1251 memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1253 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1255 if (bytes == GNUNET_SYSERR)
1257 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1258 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1259 errno, strerror(errno));
1262 GNUNET_assert(bytes != GNUNET_SYSERR);
1263 GNUNET_assert(bytes == size);
1264 GNUNET_free(msgheader);
1266 set_next_beacon_time(plugin);
1267 set_next_send(plugin);
1271 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1276 struct GNUNET_MessageHeader * msgheader;
1277 struct ieee80211_frame * ieeewlanheader;
1278 struct Radiotap_Send * radioHeader;
1279 struct FragmentationAckHeader * msgheader2;
1281 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1283 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1284 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1287 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1288 "Sending ack for message_id %u with fragment field %u, size %u\n",
1289 ack->message_id, ack->fragments_field, size
1290 - sizeof(struct Radiotap_Send));
1293 msgheader = GNUNET_malloc(size);
1294 msgheader->size = htons(size);
1295 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1297 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1298 getRadiotapHeader(plugin, ack->session, radioHeader);
1299 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1300 getWlanHeader(ieeewlanheader, &ack->session->addr, plugin);
1302 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1303 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1304 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1305 msgheader2->message_id = htonl(ack->message_id);
1306 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1308 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1309 if (bytes == GNUNET_SYSERR)
1311 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1312 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1313 errno, strerror(errno));
1316 GNUNET_assert(bytes != GNUNET_SYSERR);
1317 GNUNET_assert(bytes == size);
1318 GNUNET_free(msgheader);
1319 set_next_send(plugin);
1323 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1325 struct Finish_send * finish;
1326 struct Plugin * plugin;
1330 plugin = finish->plugin;
1332 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1334 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1335 finish->msgheader, finish->size);
1336 GNUNET_assert(bytes != GNUNET_SYSERR);
1338 if (bytes != finish->size)
1341 finish->msgheader = finish->msgheader + bytes;
1342 finish->size = finish->size - bytes;
1343 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1344 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1345 &finish_sending, finish);
1349 GNUNET_free(finish->msgstart);
1350 GNUNET_free(finish);
1352 set_next_send(plugin);
1359 * Function called when wlan helper is ready to get some data
1361 * @param cls closure
1362 * @param tc GNUNET_SCHEDULER_TaskContext
1365 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1368 struct Plugin * plugin = cls;
1369 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1371 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1374 struct Session * session;
1375 struct FragmentMessage * fm;
1376 struct ieee80211_frame * ieeewlanheader;
1377 struct Radiotap_Send * radioHeader;
1378 struct GNUNET_MessageHeader * msgheader;
1380 struct FragmentationHeader fragheader;
1381 struct FragmentationHeader * fragheaderptr;
1382 struct Finish_send * finish;
1383 struct AckSendQueue * ack;
1386 const char * copystart;
1389 struct GNUNET_TIME_Absolute next_send;
1391 if (plugin->ack_send_queue_head != NULL)
1393 ack = plugin->ack_send_queue_head;
1394 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1395 plugin->ack_send_queue_tail, ack);
1396 send_ack(plugin, ack);
1401 //test if a "hello-beacon" has to be send
1402 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1404 send_hello_beacon(plugin);
1410 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1414 session = fm->session;
1415 GNUNET_assert(session != NULL);
1417 // test if message timed out
1418 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1421 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1424 free_fragment_message(plugin, fm);
1425 check_fragment_queue(plugin);
1431 //if (fm->message_size > WLAN_MTU)
1433 size = sizeof(struct FragmentationHeader);
1435 set_next_message_fragment_pos(plugin, fm);
1437 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1440 fragheader.fragment_off_or_num = htons(fm->message_pos);
1441 fragheader.message_id = htonl(fm->message_id_out);
1442 copystart = fm->msg + copyoffset;
1443 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1444 WLAN_MTU - sizeof(struct FragmentationHeader));
1448 GNUNET_ERROR_TYPE_DEBUG,
1449 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1450 fm->message_id_out, fm->message_pos, copysize
1451 + sizeof(struct FragmentationHeader), copyoffset,
1452 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1455 if (copyoffset >= fm->message_size)
1458 GNUNET_ERROR_TYPE_ERROR,
1459 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1460 copyoffset, fm->message_size, WLAN_MTU
1461 - sizeof(struct FragmentationHeader), copysize,
1464 GNUNET_assert(copyoffset < fm->message_size);
1465 //FIXME remove later
1466 GNUNET_assert(copystart < fm->msg + fm->message_size);
1468 fragheader.header.size = htons(copysize
1469 + sizeof(struct FragmentationHeader));
1470 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1475 // there is no need to split
1476 copystart = fm->msg;
1477 copysize = fm->message_size;
1481 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1482 + sizeof(struct GNUNET_MessageHeader);
1483 msgheader = GNUNET_malloc(size);
1484 msgheader->size = htons(size);
1485 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1487 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1488 getRadiotapHeader(plugin, session, radioHeader);
1490 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1491 getWlanHeader(ieeewlanheader, &fm->session->addr, plugin);
1493 //could be faster if content is just send and not copyed before
1494 //fragmentheader is needed
1495 //if (fm->message_size > WLAN_MTU)
1497 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1498 memcpy(&ieeewlanheader[1], &fragheader,
1499 sizeof(struct FragmentationHeader));
1500 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1501 memcpy(&fragheaderptr[1], copystart, copysize);
1505 memcpy(&ieeewlanheader[1], copystart, copysize);
1508 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1510 if (bytes == GNUNET_SYSERR)
1513 GNUNET_ERROR_TYPE_ERROR,
1514 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1515 errno, strerror(errno));
1518 GNUNET_assert(bytes != GNUNET_SYSERR);
1520 //check if this was the last fragment of this message, if true then queue at the end of the list
1521 if (copysize + copyoffset >= fm->message_size)
1523 GNUNET_assert(copysize + copyoffset == fm->message_size);
1525 GNUNET_CONTAINER_heap_update_cost(
1526 plugin->pending_Fragment_Messages, fm->node, MIN(
1527 fm->timeout.abs_value, fm->next_ack.abs_value));
1528 // if fragments have opimized timeouts
1529 //sort_fragment_into_queue(plugin,fm);
1531 #if DEBUG_wlan_retransmission
1533 GNUNET_ERROR_TYPE_DEBUG,
1534 "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1535 fm->message_id_out, fm->message_id_out, fm->message_pos,
1536 fm->message_size, GNUNET_TIME_absolute_get_remaining(
1543 finish = GNUNET_malloc(sizeof( struct Finish_send));
1544 finish->plugin = plugin;
1545 finish->msgheader = (char *) msgheader + bytes;
1546 finish->size = size - bytes;
1547 finish->msgstart = msgheader;
1548 finish ->next_send = next_send;
1550 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1552 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1553 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1554 &finish_sending, finish);
1559 GNUNET_assert(bytes == size);
1560 GNUNET_free(msgheader);
1561 set_next_send(plugin);
1567 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1568 "do_transmit did nothing, should not happen!\n");
1572 * Another peer has suggested an address for this
1573 * peer and transport plugin. Check that this could be a valid
1574 * address. If so, consider adding it to the list
1577 * @param cls closure
1578 * @param addr pointer to the address
1579 * @param addrlen length of addr
1580 * @return GNUNET_OK if this is a plausible address for this peer
1584 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1586 //struct Plugin *plugin = cls;
1588 /* check if the address is plausible; if so,
1589 add it to our list! */
1591 GNUNET_assert(cls !=NULL);
1592 //FIXME mitm is not checked
1593 //Mac Address has 6 bytes
1596 /* TODO check for bad addresses like multicast, broadcast, etc */
1600 return GNUNET_SYSERR;
1604 * Function that can be used by the transport service to transmit
1605 * a message using the plugin.
1607 * @param cls closure
1608 * @param target who should receive this message
1609 * @param priority how important is the message
1610 * @param msgbuf the message to transmit
1611 * @param msgbuf_size number of bytes in 'msgbuf'
1612 * @param timeout when should we time out
1613 * @param session which session must be used (or NULL for "any")
1614 * @param addr the address to use (can be NULL if the plugin
1615 * is "on its own" (i.e. re-use existing TCP connection))
1616 * @param addrlen length of the address in bytes
1617 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1618 * otherwise the plugin may use other addresses or
1619 * existing connections (if available)
1620 * @param cont continuation to call once the message has
1621 * been transmitted (or if the transport is ready
1622 * for the next transmission call; or if the
1623 * peer disconnected...)
1624 * @param cont_cls closure for cont
1625 * @return number of bytes used (on the physical network, with overheads);
1626 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1627 * and does NOT mean that the message was not transmitted (DV)
1630 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1631 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1632 struct GNUNET_TIME_Relative timeout, struct Session *session,
1633 const void *addr, size_t addrlen, int force_address,
1634 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1636 struct Plugin * plugin = cls;
1637 struct PendingMessage * newmsg;
1638 struct WlanHeader * wlanheader;
1640 //check if msglen > 0
1641 GNUNET_assert(msgbuf_size > 0);
1643 //get session if needed
1644 if (session == NULL)
1646 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1648 session = get_session(plugin, addr);
1652 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1653 _("Wlan Address len %d is wrong\n"), addrlen);
1658 //TODO target "problem" not solved
1659 //if (session->target != NULL){
1660 // GNUNET_assert(session->target == *target);
1662 session->target = *target;
1668 //queue message in session
1669 //test if there is no other message in the "queue"
1670 //FIXME: to many send requests
1671 //GNUNET_assert (session->pending_message == NULL);
1672 if (session->pending_message != NULL)
1674 newmsg = session->pending_message;
1676 GNUNET_ERROR_TYPE_ERROR,
1677 "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",
1678 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1679 session->fragment_messages_out_count);
1680 if (session->pending_message2 != NULL)
1683 GNUNET_ERROR_TYPE_ERROR,
1684 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1689 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1690 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1691 wlanheader = (struct WlanHeader *) newmsg->msg;
1692 //copy msg to buffer, not fragmented / segmented yet, but with message header
1693 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1694 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1695 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1696 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1697 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1698 newmsg->transmit_cont = cont;
1699 newmsg->transmit_cont_cls = cont_cls;
1700 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1702 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1704 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1706 if (session->pending_message == NULL)
1708 session->pending_message = newmsg;
1712 session->pending_message2 = newmsg;
1716 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1717 "New message for %p with size (incl wlan header) %u added\n", session,
1718 newmsg->message_size);
1722 queue_session(plugin, session);
1724 check_fragment_queue(plugin);
1725 //FIXME not the correct size
1731 * Iterate over the fragment messages of the given session.
1733 * @param cls argument to give to iterator
1734 * @param node node to iterate over
1735 * @param element value stored at the node
1736 * @param cost cost associated with the node
1737 * @return GNUNET_YES if we should continue to iterate,
1741 free_fragment_message_from_session(void *cls,
1742 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1743 GNUNET_CONTAINER_HeapCostType cost)
1745 struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
1746 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1748 if (fm->session == pair->session)
1751 free_fragment_message(pair->plugin, fm);
1758 * Search for fragment message with given id and session
1760 * @param cls argument to give to iterator
1761 * @param node node to iterate over
1762 * @param element value stored at the node
1763 * @param cost cost associated with the node
1764 * @return GNUNET_YES if we should continue to iterate,
1768 search_fragment_message_from_session_and_id(void *cls,
1769 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1770 GNUNET_CONTAINER_HeapCostType cost)
1772 struct Session_id_pair * pair = (struct Session_id_pair *) cls;
1773 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1775 if ((fm->session == pair->session)
1776 && (fm->message_id_out == pair->message_id))
1786 * function to get the message in the fragement queue (out) of a session with a specific id
1787 * @param session pointer to the session
1788 * @param message_id id of the message
1789 * @return pointer to the struct FragmentMessage
1791 static struct FragmentMessage *
1792 get_fragment_message_from_session_and_id(struct Plugin * plugin,
1793 struct Session * session, uint32_t message_id)
1795 struct Session_id_pair pair;
1796 pair.session = session;
1797 pair.message_id = message_id;
1798 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1799 &search_fragment_message_from_session_and_id, &pair);
1804 * function to get the receive message of a session
1805 * @param plugin pointer to the plugin struct
1806 * @param session session this fragment belongs to
1808 struct Receive_Message_Queue *
1809 get_receive_message_from_session(struct Plugin * plugin,
1810 struct Session * session)
1812 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1813 while (rec_message != NULL)
1815 if (rec_message->session == session)
1819 rec_message = rec_message->next;
1825 * Function to dispose the fragments received for a message and the message
1826 * @param plugin pointer to the plugin struct
1827 * @param rec_message pointer to the struct holding the message which should be freed
1830 free_receive_message(struct Plugin* plugin,
1831 struct Receive_Message_Queue * rx_message)
1833 GNUNET_assert(rx_message !=NULL);
1834 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1835 struct Receive_Fragment_Queue * rec_queue2;
1837 while (rec_queue != NULL)
1839 rec_queue2 = rec_queue;
1840 rec_queue = rec_queue->next;
1841 GNUNET_free(rec_queue2);
1844 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
1846 GNUNET_assert(plugin->pending_receive_messages > 0);
1847 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
1849 plugin->pending_receive_messages--;
1850 rx_message->session->fragment_messages_in_count--;
1851 GNUNET_free(rx_message);
1855 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
1857 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1858 struct PendingMessage * pm;
1859 struct Receive_Message_Queue * receive_queue;
1860 struct Plugin_Session_pair pair;
1863 //is this session pending for send
1864 while (pendingsession != NULL)
1866 if (pendingsession->content == queue->content)
1868 plugin->pendingsessions--;
1869 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1870 plugin->pending_Sessions_tail, pendingsession);
1871 GNUNET_free(pendingsession);
1874 pendingsession = pendingsession->next;
1877 //is something of this session in the fragment queue?
1878 pair.plugin = plugin;
1879 pair.session = queue->content;
1880 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1881 &free_fragment_message_from_session, &pair);
1883 //dispose all received fragments
1884 receive_queue = get_receive_message_from_session(plugin, queue->content);
1885 while (receive_queue != NULL)
1887 free_receive_message(plugin, receive_queue);
1888 receive_queue = get_receive_message_from_session(plugin, queue->content);
1891 // remove PendingMessage
1892 pm = queue->content->pending_message;
1895 GNUNET_free_non_null(pm->msg);
1899 // remove PendingMessage
1900 pm = queue->content->pending_message2;
1903 GNUNET_free_non_null(pm->msg);
1907 GNUNET_free(queue->content);
1908 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1910 plugin->session_count--;
1912 check_fragment_queue(plugin);
1917 * Function that can be used to force the plugin to disconnect
1918 * from the given peer and cancel all previous transmissions
1919 * (and their continuation).
1921 * @param cls closure
1922 * @param target peer from which to disconnect
1925 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1927 struct Plugin *plugin = cls;
1928 struct Sessionqueue * queue = plugin->sessions;
1930 // just look at all the session for the needed one
1931 while (queue != NULL)
1933 // content is never NULL
1934 GNUNET_assert (queue->content != NULL);
1935 if (memcmp(target, &(queue->content->target),
1936 sizeof(struct GNUNET_PeerIdentity)) == 0)
1938 free_session(plugin, queue);
1942 queue = queue->next;
1947 * Convert the transports address to a nice, human-readable
1950 * @param cls closure
1951 * @param type name of the transport that generated the address
1952 * @param addr one of the addresses of the host, NULL for the last address
1953 * the specific address format depends on the transport
1954 * @param addrlen length of the address
1955 * @param numeric should (IP) addresses be displayed in numeric form?
1956 * @param timeout after how long should we give up?
1957 * @param asc function to call on each string
1958 * @param asc_cls closure for asc
1961 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1962 const void *addr, size_t addrlen, int numeric,
1963 struct GNUNET_TIME_Relative timeout,
1964 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1967 const unsigned char * input;
1969 //GNUNET_assert(cls !=NULL);
1972 /* invalid address (MAC addresses have 6 bytes) */
1977 input = (const unsigned char*) addr;
1978 GNUNET_snprintf(ret, sizeof(ret),
1979 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1980 input[0], input[1], input[2], input[3], input[4], input[5]);
1985 * function to check if bitfield is representation of fragments of the message
1986 * @param rec_message message to check
1990 check_message_fragment_bitfield(struct Receive_Message_Queue * rx_msg)
1992 uint64_t checkfragments = 0;
1993 struct Receive_Fragment_Queue * rx_frag = rx_msg->frag_head;
1995 while (rx_frag != NULL)
1997 setBit((char*) &checkfragments, rx_frag->num);
1998 rx_frag = rx_frag->next;
2001 GNUNET_assert(checkfragments == rx_msg->received_fragments);
2005 * Function to test if fragment number already exists in the fragments received
2007 * @param rec_message message this fragment belongs to
2008 * @param fh Fragmentheader of the fragment
2009 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2013 is_double_msg(struct Receive_Message_Queue * rx_msg,
2014 struct FragmentationHeader * fh)
2016 //test if bitfield is okay
2018 check_message_fragment_bitfield(rx_msg);
2021 return testBit((char *) &rx_msg->received_fragments, ntohs(
2022 fh->fragment_off_or_num));
2027 * Function to insert a fragment in a queue of a message
2028 * @param session session the fragment belongs to
2029 * @param rec_queue fragment to add
2033 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2034 struct Receive_Fragment_Queue * rx_frag)
2036 GNUNET_assert(rx_message != NULL);
2037 GNUNET_assert(rx_frag != NULL);
2039 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2040 struct WlanHeader * wlanheader;
2042 //this is the first fragment of the message (fragment id 0)
2043 if (rx_frag->num == 0)
2045 wlanheader = (struct WlanHeader *) rx_frag->msg;
2046 rx_message->rec_size = ntohs(wlanheader->header.size);
2050 while (rx_frag2 != NULL)
2052 if (rx_frag2->num > rx_frag->num)
2054 //next element number is grater than the current num
2055 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2056 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2059 rx_frag2 = rx_frag2->next;
2062 //no element has a grater number
2063 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2065 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2069 * handels the data after all fragments are put together
2071 * @param session_light
2072 * @param hdr pointer to the data
2075 wlan_data_message_handler(struct Plugin * plugin,
2076 struct Session_light * session_light,
2077 const struct GNUNET_MessageHeader * hdr)
2079 struct WlanHeader * wlanheader;
2080 struct Session * session;
2081 const char * tempmsg;
2082 const struct GNUNET_MessageHeader * temp_hdr;
2083 struct GNUNET_PeerIdentity tmptarget;
2085 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2090 GNUNET_ERROR_TYPE_DEBUG,
2091 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2095 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2096 + sizeof(struct GNUNET_MessageHeader))
2098 //packet not big enought
2102 GNUNET_assert(session_light != NULL);
2103 if (session_light->session == NULL)
2105 session_light->session = search_session(plugin, &session_light->addr);
2107 session = session_light->session;
2108 wlanheader = (struct WlanHeader *) hdr;
2110 tempmsg = (char*) &wlanheader[1];
2111 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2113 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2116 //wrong crc, dispose message
2117 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2118 "Wlan message Header crc was wrong\n");
2122 //if not in session list
2123 if (session == NULL)
2127 GNUNET_ERROR_TYPE_DEBUG,
2128 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2129 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2130 sizeof(struct WlanHeader));
2132 //try if it is a hello message
2133 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2134 + sizeof(struct WlanHeader))
2136 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2138 if (GNUNET_HELLO_get_id(
2139 (const struct GNUNET_HELLO_Message *) temp_hdr,
2140 &tmptarget) == GNUNET_OK)
2142 session = create_session(plugin, &session_light->addr);
2143 session_light->session = session;
2144 memcpy(&session->target, &tmptarget,
2145 sizeof(struct GNUNET_PeerIdentity));
2149 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2150 "WLAN client not in session list and hello message not okay\n");
2157 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2158 "WLAN client not in session list and not a hello message\n");
2165 GNUNET_ERROR_TYPE_WARNING,
2166 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2167 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2168 sizeof(struct WlanHeader));
2173 //"receive" the message
2176 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2177 (const char *) temp_hdr,
2178 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2184 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2185 "wlan_data_message_handler got wrong message type\n");
2191 * Function to check if all fragments of a message have been received
2192 * @param plugin the plugin handle
2193 * @param session_light information of the message sender
2194 * @param session session the message belongs to
2195 * @param rec_message pointer to the message that should be checked
2199 check_rx_finished_msg(struct Plugin* plugin,
2200 struct Session_light * session_light, struct Session * session,
2201 struct Receive_Message_Queue * rx_message)
2203 GNUNET_assert(rx_message !=NULL);
2205 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2206 int packetsize = rx_message->rec_size;
2209 uint64_t bitfield = 0;
2212 //check if first fragment is present
2213 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2217 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2219 else if (packetsize < sizeof(struct WlanHeader)
2220 + sizeof(struct GNUNET_MessageHeader))
2223 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2225 free_receive_message(plugin, rx_message);
2230 check_message_fragment_bitfield(rx_message);
2233 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2235 bitfield = ~bitfield;
2236 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2237 if (rx_message->received_fragments == bitfield)
2240 while (rx_frag != NULL)
2242 sum += rx_frag->size;
2243 rx_frag = rx_frag->next;
2245 //sum should always be smaller or equal of
2246 GNUNET_assert(sum <= packetsize);
2247 if (sum == packetsize)
2251 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2252 "check_rec_finished_msg: A message for %p is complete\n", session);
2256 //copy fragments together
2257 msg = GNUNET_malloc(packetsize);
2258 rx_frag = rx_message->frag_head;
2260 while (rx_frag != NULL)
2262 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2263 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2264 aktnum += rx_frag->size;
2265 rx_frag = rx_frag->next;
2268 free_receive_message(plugin, rx_message);
2269 //call wlan_process_helper to process the message
2270 wlan_data_message_handler(plugin, session_light,
2271 (struct GNUNET_MessageHeader*) msg);
2272 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2281 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2284 GNUNET_assert(client != NULL);
2285 GNUNET_assert(cls != NULL);
2286 struct Session * session = (struct Session *) client;
2287 struct Plugin * plugin = (struct Plugin *) cls;
2289 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2290 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2291 distance[0].value = htonl(1);
2292 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2293 distance[1].value = htonl(0);
2296 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2297 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2298 wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
2302 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2303 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2304 (const char*) &session->addr, sizeof(session->addr));
2308 * function to add an ack to send it for a received fragment
2309 * @param plugin pointer to the global plugin structure
2310 * @param session pointer to the session this ack belongs to
2311 * @param bitfield bitfield to send
2312 * @param fh pointer to the fragmentation header which we would like to acknolage
2316 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2317 uint64_t bitfield, struct FragmentationHeader * fh)
2319 struct AckSendQueue * ack;
2321 GNUNET_assert(plugin != NULL);
2322 GNUNET_assert(session != NULL);
2323 GNUNET_assert(fh != NULL);
2325 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2326 ack->fragments_field = bitfield;
2327 ack->message_id = ntohl(fh->message_id);
2328 ack->session = session;
2330 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2331 plugin->ack_send_queue_tail, ack);
2336 * function to get the receive message from the message id and the session
2337 * @param plugin pointer to the plugin struct
2338 * @param session session this fragment belongs to
2339 * @param message_id id of the message
2342 struct Receive_Message_Queue *
2343 get_receive_message(struct Plugin * plugin, struct Session * session,
2344 uint32_t message_id)
2346 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2347 while (rec_message != NULL)
2349 if ((rec_message->message_id_in == message_id) && (rec_message->session
2354 rec_message = rec_message->next;
2360 * function to insert a received fragment into the right fragment queue of the right message
2361 * @param plugin pointer to the plugin struct
2362 * @param session_light pointer to the session_light struct of this message
2363 * @param session session this fragment belongs to
2364 * @param fh pointer to the header of the fragment
2365 * @return new fragment bitfield for the message
2369 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2370 struct Session_light * session_light, struct Session * session,
2371 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2373 struct Receive_Fragment_Queue * rx_frag = NULL;
2374 struct Receive_Message_Queue * rx_message;
2375 const char * tempmsg = (char*) &fh[1];
2376 uint64_t retval = 0;
2378 //TODO fragments do not timeout
2379 //check if message_id is right or it is a new msg
2380 GNUNET_assert(fh != NULL);
2382 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2384 if (rx_message == NULL)
2386 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2389 //new message incoming
2390 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2391 rx_message->message_id_in = ntohl(fh->message_id);
2392 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2393 rx_message->session = session;
2394 rx_message->timeout = GNUNET_TIME_absolute_add(
2395 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2396 rx_message->received_fragments = 0;
2398 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2400 session->fragment_messages_in_count++;
2401 plugin->pending_receive_messages++;
2405 GNUNET_ERROR_TYPE_DEBUG,
2406 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2407 rx_message->message_id_in, session->fragment_messages_in_count,
2408 plugin->pending_receive_messages);
2415 GNUNET_ERROR_TYPE_INFO,
2416 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
2417 get_receive_message_from_session(plugin, session)->message_id_in);
2418 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2423 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2427 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2428 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2429 rx_frag->size = ntohs(fh->header.size)
2430 - sizeof(struct FragmentationHeader);
2431 rx_frag->num = ntohs(fh->fragment_off_or_num);
2432 rx_frag->msg = (char*) &(rx_frag[1]);
2433 //copy msg to buffer
2434 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2435 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2436 insert_fragment_in_queue(rx_message, rx_frag);
2438 retval = rx_message->received_fragments;
2442 GNUNET_ERROR_TYPE_DEBUG,
2443 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2444 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2445 rx_message->received_fragments, session);
2448 check_rx_finished_msg(plugin, session_light, session, rx_message);
2452 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2453 retval = rx_message->received_fragments;
2461 * Function used for to process the data received from the wlan interface
2463 * @param cls the plugin handle
2464 * @param session_light FIXME: document
2465 * @param hdr hdr of the GNUNET_MessageHeader
2468 wlan_data_helper(void *cls, struct Session_light * session_light,
2469 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2471 struct Plugin *plugin = cls;
2472 struct Session * session;
2474 struct FragmentationHeader * fh;
2475 struct FragmentationAckHeader * fah;
2476 struct FragmentMessage * fm;
2478 const char * tempmsg;
2480 uint64_t fragment_bitfield = 0;
2483 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2486 //TODO better DOS protection, error handling
2487 //TODO test first than create session
2488 GNUNET_assert(session_light != NULL);
2492 GNUNET_ERROR_TYPE_DEBUG,
2493 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2494 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2495 session_light->addr.mac, 6));
2498 if (session_light->session == NULL)
2500 session_light->session = get_session(plugin, &session_light->addr);
2502 GNUNET_assert(GNUNET_HELLO_get_id(
2503 (const struct GNUNET_HELLO_Message *) &hdr[1],
2504 &(session_light->session->target) ) != GNUNET_SYSERR);
2510 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2513 GNUNET_assert(session_light != NULL);
2514 if (session_light->session == NULL)
2516 session_light->session = search_session(plugin, &session_light->addr);
2518 session = session_light->session;
2520 fh = (struct FragmentationHeader *) hdr;
2521 tempmsg = (char*) &fh[1];
2525 GNUNET_ERROR_TYPE_DEBUG,
2526 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2527 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2528 hdr->size), wlan_plugin_address_to_string(NULL,
2529 session_light->addr.mac, 6));
2532 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2534 //wrong crc, dispose message
2535 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2539 //if in the session list
2540 if (session != NULL)
2542 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2543 session_light, session, fh, rxinfo);
2549 GNUNET_ERROR_TYPE_INFO,
2550 "WLAN client not in session list, fragment num %u, message id %u\n",
2551 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2552 wlan_data_message_handler(plugin, session_light,
2553 (struct GNUNET_MessageHeader *) tempmsg);
2554 session = session_light->session;
2555 //test if a session was created
2556 if (session == NULL)
2560 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2563 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2564 set_next_send(plugin);
2570 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2575 GNUNET_ERROR_TYPE_DEBUG,
2576 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2577 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2578 session_light->addr.mac, 6));
2581 GNUNET_assert(session_light != NULL);
2582 if (session_light->session == NULL)
2584 session_light->session = search_session(plugin, &session_light->addr);
2585 GNUNET_assert(session_light->session != NULL);
2587 session = session_light->session;
2588 fah = (struct FragmentationAckHeader *) hdr;
2589 fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
2595 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
2596 fah->fragment_field);
2597 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
2599 #if DEBUG_wlan_retransmission
2600 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
2601 fm->message_id_out, fm->ack_bitfield);
2603 check_finished_fragment(plugin, fm);
2604 set_next_send(plugin);
2609 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2610 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2620 GNUNET_ERROR_TYPE_INFO,
2621 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2622 ntohs(hdr->type), ntohs(hdr->size));
2628 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2629 "Helper finished\n");
2635 macprinter(const u_int8_t * mac)
2637 static char macstr[20];
2639 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2640 mac[2], mac[3], mac[4], mac[5]);
2645 * Function used for to process the data from the suid process
2647 * @param cls the plugin handle
2648 * @param client client that send the data (not used)
2649 * @param hdr header of the GNUNET_MessageHeader
2652 wlan_process_helper(void *cls, void *client,
2653 const struct GNUNET_MessageHeader *hdr)
2655 struct Plugin *plugin = cls;
2656 struct ieee80211_frame * wlanIeeeHeader = NULL;
2657 struct Session_light * session_light = NULL;
2658 struct Radiotap_rx * rxinfo;
2659 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2664 switch (ntohs(hdr->type))
2666 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2669 GNUNET_ERROR_TYPE_DEBUG,
2670 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2674 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2675 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2676 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2679 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2680 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2681 hdr->size), sizeof(struct ieee80211_frame)
2682 + sizeof(struct GNUNET_MessageHeader));
2685 /* FIXME: restart SUID process */
2688 rxinfo = (struct Radiotap_rx *) &hdr[1];
2689 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2691 //process only if it is an broadcast or for this computer both with the gnunet bssid
2694 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
2695 sizeof(struct MacAddress)) == 0)
2697 //check for broadcast or mac
2698 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2699 sizeof(struct MacAddress) == 0) || memcmp(
2700 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2701 sizeof(struct MacAddress)) == 0)
2704 // process the inner data
2707 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2708 - sizeof(struct GNUNET_MessageHeader)
2709 - sizeof(struct Radiotap_rx);
2711 session_light = GNUNET_malloc(sizeof(struct Session_light));
2712 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2713 sizeof(struct MacAddress));
2714 //session_light->session = search_session(plugin,session_light->addr);
2717 while (pos < datasize)
2719 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2722 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2723 pos += ntohs(temp_hdr->size);
2728 GNUNET_free(session_light);
2733 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2734 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2735 wlanIeeeHeader->i_addr1));
2742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2743 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2744 wlanIeeeHeader->i_addr2));
2748 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2749 //TODO more control messages
2750 //TODO use struct wlan_helper_control
2751 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2754 /* FIXME: restart SUID process */
2757 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2759 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2760 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2761 wlan_plugin_address_to_string(cls, &plugin->mac_address,
2762 sizeof(struct MacAddress)));
2764 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2765 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2774 * We have been notified that wlan-helper has written something to stdout.
2775 * Handle the output, then reschedule this function to be called again once
2776 * more is available.
2778 * @param cls the plugin handle
2779 * @param tc the scheduling context
2782 wlan_plugin_helper_read(void *cls,
2783 const struct GNUNET_SCHEDULER_TaskContext *tc)
2785 struct Plugin *plugin = cls;
2786 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2791 "Start reading from STDIN\n");
2794 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2797 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2800 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2805 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2806 _("Finished reading from wlan-helper stdout with code: %d\n"),
2811 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2812 GNUNET_NO, GNUNET_NO);
2814 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2815 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2816 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2817 &wlan_plugin_helper_read, plugin);
2821 * Start the gnunet-wlan-helper process.
2823 * @param plugin the transport plugin
2824 * @param testmode should we use the dummy driver for testing?
2825 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2828 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2830 const char * filename = "gnunet-transport-wlan-helper";
2831 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2832 if (plugin->server_stdout == NULL)
2833 return GNUNET_SYSERR;
2835 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2836 if (plugin->server_stdin == NULL)
2837 return GNUNET_SYSERR;
2840 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2841 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2842 plugin->interface, testmode);
2844 /* Start the server process */
2846 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2847 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2848 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2849 if (plugin->server_proc == NULL)
2852 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2853 "Failed to start gnunet-wlan-helper process\n");
2855 return GNUNET_SYSERR;
2858 /* Close the write end of the read pipe */
2859 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2861 /* Close the read end of the write pipe */
2862 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2864 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2865 GNUNET_DISK_PIPE_END_READ);
2866 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2867 GNUNET_DISK_PIPE_END_WRITE);
2869 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2872 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2873 "Adding server_read_task for the wlan-helper\n");
2876 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2877 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2878 &wlan_plugin_helper_read, plugin);
2884 * Exit point from the plugin.
2885 * @param cls pointer to the api struct
2890 libgnunet_plugin_transport_wlan_done(void *cls)
2892 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2893 struct Plugin *plugin = api->cls;
2894 struct Sessionqueue * queue = plugin->sessions;
2895 struct FragmentMessage * fm;
2898 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2899 "libgnunet_plugin_transport_wlan_done started\n");
2902 GNUNET_assert(cls !=NULL);
2904 if (plugin->suid_tokenizer != NULL)
2905 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2907 if (plugin->data_tokenizer != NULL)
2908 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
2911 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
2913 free_fragment_message(plugin, fm);
2914 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
2918 while (queue != NULL)
2920 free_session(plugin, queue);
2923 GNUNET_free_non_null(plugin->interface);
2924 GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
2925 GNUNET_free (plugin);
2931 * Entry point for the plugin.
2933 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2934 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2937 libgnunet_plugin_transport_wlan_init(void *cls)
2939 //struct GNUNET_SERVICE_Context *service;
2940 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2941 struct GNUNET_TRANSPORT_PluginFunctions *api;
2942 struct Plugin *plugin;
2943 static unsigned long long testmode = 0;
2945 GNUNET_assert(cls !=NULL);
2947 plugin = GNUNET_malloc (sizeof (struct Plugin));
2949 plugin->pendingsessions = 0;
2950 plugin->session_count = 0;
2951 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2952 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2953 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2954 plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
2955 GNUNET_CONTAINER_HEAP_ORDER_MIN);
2957 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
2960 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
2962 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2963 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2965 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2967 api->send = &wlan_plugin_send;
2968 api->disconnect = &wlan_plugin_disconnect;
2969 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2970 api->check_address = &wlan_plugin_address_suggested;
2971 api->address_to_string = &wlan_plugin_address_to_string;
2975 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2977 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
2978 "transport-wlan", "TESTMODE", &testmode))
2979 testmode = 0; //default value
2982 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
2984 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
2985 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
2987 libgnunet_plugin_transport_wlan_done(api);
2993 set_next_beacon_time(plugin);
2995 wlan_transport_start_wlan_helper(plugin, testmode);
2998 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3004 /* end of plugin_transport_wlan.c */