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 from the wlan helper
126 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
128 * encapsulation of packets received
130 struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
133 * stdout pipe handle for the gnunet-wlan-helper process
135 struct GNUNET_DISK_PipeHandle *server_stdout;
138 * stdout file handle for the gnunet-wlan-helper process
140 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
143 * stdin pipe handle for the gnunet-wlan-helper process
145 struct GNUNET_DISK_PipeHandle *server_stdin;
148 * stdin file handle for the gnunet-wlan-helper process
150 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
153 * ID of the gnunet-wlan-server std read task
155 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
158 * ID of the gnunet-wlan-server std read task
160 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
163 * ID of the delay task for writing
165 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
168 * The process id of the wlan process
170 struct GNUNET_OS_Process *server_proc;
173 * The interface of the wlan card given to us by the user.
178 * The mac_address of the wlan card given to us by the helper.
180 struct MacAddress mac_address;
183 * Sessions currently pending for transmission
184 * to this peer, if any.
186 struct Sessionqueue * pending_Sessions_head;
189 * Sessions currently pending for transmission
190 * to this peer (tail), if any.
192 struct Sessionqueue * pending_Sessions_tail;
195 * number of pending sessions
197 unsigned int pendingsessions;
200 * Messages in the fragmentation queue, head
202 struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
205 * Messages in the in Queue, head
207 struct Receive_Message_Queue * receive_messages_head;
210 * Messages in the in Queue, tail
212 struct Receive_Message_Queue * receive_messages_teil;
215 * number of messages in the in queue
217 unsigned int pending_receive_messages;
220 * time of the next "hello-beacon"
222 struct GNUNET_TIME_Absolute beacon_time;
225 * queue to send acks for received fragments (head)
227 struct AckSendQueue * ack_send_queue_head;
230 * queue to send acks for received fragments (tail)
232 struct AckSendQueue * ack_send_queue_tail;
237 * Struct to store data if file write did not accept the whole packet
241 struct Plugin * plugin;
243 struct GNUNET_MessageHeader * msgstart;
245 struct GNUNET_TIME_Absolute next_send;
249 * Queue of sessions, for the general session queue and the pending session queue
254 struct Sessionqueue * next;
255 struct Sessionqueue * prev;
256 struct Session * content;
260 * Queue for the fragments received
263 struct Receive_Fragment_Queue
265 struct Receive_Fragment_Queue * next;
266 struct Receive_Fragment_Queue * prev;
270 struct Radiotap_rx rxinfo;
274 struct Session_id_fragment_triple
276 struct Session * session;
278 struct FragmentMessage * fm;
282 struct Plugin_Session_pair
284 struct Plugin * plugin;
285 struct Session * session;
289 * Queue for the fragments received
291 struct Receive_Message_Queue
293 struct Receive_Message_Queue * next;
295 struct Receive_Message_Queue * prev;
298 * current number for message incoming, to distinguish between the messages
300 uint32_t message_id_in;
303 * size of the message received,
304 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
305 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
310 * Sorted queue with the fragments received; head
313 struct Receive_Fragment_Queue * frag_head;
316 * Sorted queue with the fragments received; tail
319 struct Receive_Fragment_Queue * frag_tail;
322 * Session this fragment belongs to
325 struct Session * session;
328 * Timeout value for the pending message.
330 struct GNUNET_TIME_Absolute timeout;
333 * Bitfield of received fragments
336 uint64_t received_fragments;
340 * Information kept for each message that is yet to
343 struct PendingMessage
347 * The pending message
352 * Size of the message
357 * Continuation function to call once the message
358 * has been sent. Can be NULL if there is no
359 * continuation to call.
361 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
364 * Cls for transmit_cont
366 void * transmit_cont_cls;
369 * Timeout value for the pending message.
371 struct GNUNET_TIME_Absolute timeout;
376 * Queue for acks to send for fragments recived
382 * next ack in the ack send queue
384 struct AckSendQueue * next;
386 * previous ack in the ack send queue
388 struct AckSendQueue * prev;
390 * pointer to the session this ack belongs to
392 struct Session * session;
394 * ID of message, to distinguish between the messages, picked randomly.
399 * Bit field for received fragments
401 uint64_t fragments_field;
406 * Session infos gathered from a messages
412 * the session this message belongs to
414 struct Session * session;
418 struct MacAddress addr;
422 * Session handle for connections.
430 struct SessionHeader header;
433 * Pointer to the global plugin struct.
435 struct Plugin *plugin;
438 * Message currently pending for transmission
439 * to this peer, if any.
441 struct PendingMessage *pending_message;
444 * Message currently pending for transmission
445 * to this peer, if any.
447 struct PendingMessage *pending_message2;
450 * To whom are we talking to (set to our identity
451 * if we are still waiting for the welcome message)
453 struct GNUNET_PeerIdentity target;
458 struct MacAddress addr;
461 * Address of the other peer (either based on our 'connect'
462 * call or on our 'accept' call).
467 * Last activity on this connection. Used to select preferred
470 struct GNUNET_TIME_Absolute last_activity;
473 * count of messages in the fragment out queue for this session
476 int fragment_messages_out_count;
479 * count of messages in the fragment in queue for this session
482 int fragment_messages_in_count;
492 * Struct for Messages in the fragment queue
495 struct FragmentMessage
498 * heap pointer of this message
500 struct GNUNET_CONTAINER_HeapNode * node;
503 * Session this message belongs to
506 struct Session *session;
509 * This is a doubly-linked list.
511 struct FragmentMessage *next;
514 * This is a doubly-linked list.
516 struct FragmentMessage *prev;
519 * The pending message
524 * 0 if not in ack queue
531 * Timeout value for the pending message.
533 struct GNUNET_TIME_Absolute timeout;
536 * Timeout value for the pending fragments.
537 * Stores the time when the next msg fragment ack has to be received
539 struct GNUNET_TIME_Absolute next_ack;
542 * bitfield with all acks received for this message
544 uint64_t ack_bitfield;
547 * Size of the message
552 * pos / next fragment number in the message, for fragmentation/segmentation,
553 * some acks can be missing but there is still time
555 uint32_t message_pos;
558 * current number for message outgoing, to distinguish between the messages
560 uint32_t message_id_out;
564 * Header for messages which need fragmentation
566 struct FragmentationAckHeader
569 struct GNUNET_MessageHeader header;
572 * ID of message, to distinguish between the messages, picked randomly.
574 uint32_t message_id GNUNET_PACKED;
577 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
579 uint64_t fragment_field GNUNET_PACKED;
584 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
587 * Sets a bit active in the bitArray. Increment bit-specific
588 * usage counter on disk only if below 4bit max (==15).
590 * @param bitArray memory area to set the bit in
591 * @param bitIdx which bit to set
594 setBit(char *bitArray, unsigned int bitIdx)
597 unsigned int targetBit;
599 arraySlot = bitIdx / 8;
600 targetBit = (1L << (bitIdx % 8));
601 bitArray[arraySlot] |= targetBit;
605 * Checks if a bit is active in the bitArray
607 * @param bitArray memory area to set the bit in
608 * @param bitIdx which bit to test
609 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
612 testBit(char *bitArray, unsigned int bitIdx)
615 unsigned int targetBit;
618 targetBit = (1L << (bitIdx % 8));
619 if (bitArray[slot] & targetBit)
625 * get the next message number, at the moment just a random one
626 * @return returns the next valid message-number for sending packets
629 get_next_message_id()
631 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
635 * search for a session with the addr
637 * @param plugin pointer to the plugin struct
638 * @param addr pointer to the mac address of the peer
639 * @return returns the session
641 static struct Session *
642 search_session(struct Plugin *plugin, const struct MacAddress *addr)
644 struct Sessionqueue * queue = plugin->sessions;
646 while (queue != NULL)
648 GNUNET_assert (queue->content != NULL);
649 if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
650 return queue->content; /* session found */
657 * Function called for a quick conversion of the binary address to
658 * a numeric address. Note that the caller must not free the
659 * address and that the next call to this function is allowed
660 * to override the address again.
663 * @param addr binary address
664 * @param addrlen length of the address
665 * @return string representing the same address
668 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
671 const struct MacAddress *mac;
673 if (addrlen != sizeof(struct MacAddress))
679 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
680 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
681 mac->mac[4], mac->mac[5]);
686 * create a new session
688 * @param plugin pointer to the plugin struct
689 * @param addr pointer to the mac address of the peer
690 * @return returns the session
693 static struct Session *
694 create_session(struct Plugin *plugin, const struct MacAddress * addr)
696 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
698 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
700 queue->content = GNUNET_malloc (sizeof (struct Session));
701 queue->content->plugin = plugin;
702 queue->content->addr = *addr;
703 queue->content->fragment_messages_out_count = 0;
704 queue->content->fragment_messages_in_count = 0;
706 plugin->session_count++;
709 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
710 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
713 return queue->content;
717 * Get session from address, create if no session exists
719 * @param plugin pointer to the plugin struct
720 * @param addr pointer to the mac address of the peer
721 * @return returns the session
723 static struct Session *
724 get_session(struct Plugin *plugin, const struct MacAddress *addr)
726 struct Session * session = search_session(plugin, addr);
729 return create_session(plugin, addr);
733 * Queue the session to send data
734 * checks if there is a message pending
735 * checks if this session is not allready in the queue
736 * @param plugin pointer to the plugin
737 * @param session pointer to the session to add
740 queue_session(struct Plugin *plugin, struct Session * session)
742 struct Sessionqueue * queue = plugin->pending_Sessions_head;
744 if (session->pending_message != NULL)
746 while (queue != NULL)
748 // content is never NULL
749 GNUNET_assert (queue->content != NULL);
750 // is session already in queue?
751 if (session == queue->content)
759 // Session is not in the queue
761 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
762 queue->content = session;
765 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
766 plugin->pending_Sessions_tail, queue);
767 plugin->pendingsessions++;
773 * Function to schedule the write task, executed after a delay
774 * @param cls pointer to the plugin struct
775 * @param tc GNUNET_SCHEDULER_TaskContext pointer
778 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
780 struct Plugin * plugin = cls;
781 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
783 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
786 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
787 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
789 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
790 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
791 &do_transmit, plugin);
796 * Function to calculate the time of the next periodic "hello-beacon"
797 * @param plugin pointer to the plugin struct
801 set_next_beacon_time(struct Plugin * const plugin)
803 //under 10 known peers: once a second
804 if (plugin->session_count < 10)
806 plugin->beacon_time = GNUNET_TIME_absolute_add(
807 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
808 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
810 //under 30 known peers: every 10 seconds
811 else if (plugin->session_count < 30)
813 plugin->beacon_time = GNUNET_TIME_absolute_add(
814 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
815 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
817 //over 30 known peers: once a minute
820 plugin->beacon_time = GNUNET_TIME_absolute_add(
821 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
822 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
827 * Function to get the timeout value for acks for this session
828 * @param fm pointer to the FragmentMessage to get the next timeout
829 * @return time until the next ack should be received, in GNUNET_TIME_Relative
831 static struct GNUNET_TIME_Relative
832 get_ack_timeout(struct FragmentMessage * fm)
834 return FRAGMENT_TIMEOUT;
838 * Function to set the timer for the next timeout of the fragment queue
839 * @param plugin the handle to the plugin struct
843 set_next_send(struct Plugin * const plugin)
845 struct FragmentMessage * fm;
846 struct GNUNET_TIME_Relative next_send;
847 struct GNUNET_TIME_Absolute next_send_tmp;
850 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
852 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
853 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
856 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
858 //check if some acks are in the queue
859 if (plugin->ack_send_queue_head != NULL)
861 next_send = GNUNET_TIME_UNIT_ZERO;
864 //check if there are some fragments in the queue
867 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
870 next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
872 next_send = GNUNET_TIME_relative_min(next_send,
873 GNUNET_TIME_absolute_get_remaining(next_send_tmp));
880 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
881 next_send.rel_value);
885 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
887 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
889 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
890 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
891 &do_transmit, plugin);
896 plugin->server_write_delay_task
897 = GNUNET_SCHEDULER_add_delayed(next_send,
898 &delay_fragment_task, plugin);
903 * Function to get the next queued Session, removes the session from the queue
904 * @param plugin pointer to the plugin struct
905 * @return pointer to the session found, returns NULL if there is now session in the queue
907 static struct Session *
908 get_next_queue_session(struct Plugin * plugin)
910 struct Session * session;
911 struct Sessionqueue * sessionqueue;
912 struct Sessionqueue * sessionqueue_alt;
913 struct PendingMessage * pm;
914 sessionqueue = plugin->pending_Sessions_head;
916 while (sessionqueue != NULL)
918 session = sessionqueue->content;
920 GNUNET_assert(session != NULL);
921 pm = session->pending_message;
927 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
928 "pending message is empty, should not happen. session %p\n",
933 GNUNET_assert(pm != NULL);
935 //check for message timeout
936 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
938 //check if session has no message in the fragment queue
939 if (session->fragment_messages_out_count
940 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
942 plugin->pendingsessions--;
943 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
944 plugin->pending_Sessions_tail, sessionqueue);
945 GNUNET_free(sessionqueue);
951 sessionqueue = sessionqueue->next;
957 session->pending_message = session->pending_message2;
958 session->pending_message2 = NULL;
960 //call the cont func that it did not work
961 if (pm->transmit_cont != NULL)
962 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
964 GNUNET_free(pm->msg);
967 if (session->pending_message == NULL)
969 sessionqueue_alt = sessionqueue;
970 sessionqueue = sessionqueue->next;
971 plugin->pendingsessions--;
972 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
973 plugin->pending_Sessions_tail, sessionqueue_alt);
975 GNUNET_free(sessionqueue_alt);
985 * frees the space of a message in the fragment queue (send queue)
986 * @param plugin the plugin struct
987 * @param fm message to free
990 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
992 struct Session * session = fm->session;
996 (session->fragment_messages_out_count)--;
997 GNUNET_free_non_null(fm->msg);
998 GNUNET_CONTAINER_heap_remove_node(fm->node);
1001 queue_session(plugin, session);
1003 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1004 "free pending fragment messages, pending messages remaining %u\n",
1005 GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
1011 * Function to check if there is some space in the fragment queue
1012 * inserts a message if space is available
1013 * @param plugin the plugin struct
1017 check_fragment_queue(struct Plugin * plugin)
1019 struct Session * session;
1020 struct FragmentMessage * fm;
1021 struct GNUNET_PeerIdentity pid;
1023 struct PendingMessage * pm;
1025 if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1026 < FRAGMENT_QUEUE_SIZE)
1028 session = get_next_queue_session(plugin);
1029 if (session != NULL)
1031 pm = session->pending_message;
1032 session->pending_message = NULL;
1033 session->fragment_messages_out_count++;
1034 GNUNET_assert(pm != NULL);
1036 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1037 fm->message_size = pm->message_size;
1039 fm->session = session;
1040 fm->timeout.abs_value = pm->timeout.abs_value;
1041 fm->message_pos = 0;
1042 fm->next_ack = GNUNET_TIME_absolute_get();
1043 fm->message_id_out = get_next_message_id();
1044 fm->ack_bitfield = 0;
1045 fm->node = GNUNET_CONTAINER_heap_insert(
1046 plugin->pending_Fragment_Messages, fm,
1047 GNUNET_TIME_absolute_get().abs_value);
1049 GNUNET_assert(session !=NULL);
1051 if (pm->transmit_cont != NULL)
1053 pid = session->target;
1054 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1056 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1057 "called pm->transmit_cont for %p\n", session);
1063 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1064 "no pm->transmit_cont for %p\n", session);
1069 if (session->pending_message2 != NULL)
1071 session->pending_message = session->pending_message2;
1072 session->pending_message2 = NULL;
1074 queue_session(plugin, session);
1080 //check if timeout changed
1081 set_next_send(plugin);
1085 * Funktion to check if all fragments where send and the acks received
1086 * frees the space if finished
1087 * @param plugin the plugin struct
1088 * @param fm the message to check
1091 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1093 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1094 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1095 - sizeof(struct FragmentationHeader)));
1096 uint64_t tmpfield = UINT64_MAX;
1097 tmpfield = tmpfield >> maxack;
1101 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1102 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1103 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1106 if (fm->ack_bitfield == tmpfield)
1109 #if DEBUG_wlan_retransmission
1110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1111 "Finished sending and got all acks; message_id %u\n",
1112 fm->message_id_out);
1115 free_fragment_message(plugin, fm);
1117 check_fragment_queue(plugin);
1123 * Function to set the next fragment number
1124 * @param fm use this FragmentMessage
1128 set_next_message_fragment_pos(struct Plugin * plugin,
1129 struct FragmentMessage * fm)
1134 //check if retransmit is needed
1135 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1138 // be positive and try again later :-D
1139 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1140 // find first missing fragment
1142 fm->message_pos = 0;
1144 GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1147 #if DEBUG_wlan_retransmission
1148 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1149 "Retransmit; message_id %u; fragment number %i, size: %u\n",
1150 fm->message_id_out, fm->message_pos, fm->message_size);
1154 //test if ack 0 (or X) was already received
1155 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1164 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1165 struct Radiotap_Send * header)
1168 if (session != NULL)
1170 header->rate = session->rate;
1171 header->tx_power = session->tx_power;
1172 header->antenna = session->antenna;
1177 header->tx_power = 0;
1178 header->antenna = 0;
1185 * function to generate the wlan hardware header for one packet
1186 * @param Header address to write the header to
1187 * @param to_mac_addr address of the recipient
1188 * @param plugin pointer to the plugin struct
1189 * @return GNUNET_YES if there was no error
1192 getWlanHeader(struct ieee80211_frame * Header,
1193 const struct MacAddress * to_mac_addr, struct Plugin * plugin,
1197 const int rate = 11000000;
1199 Header->i_fc[0] = 0x08;
1200 Header->i_fc[1] = 0x00;
1201 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1202 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1203 memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
1205 tmp16 = (uint16_t*) Header->i_dur;
1206 *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
1214 * @param msgbuf pointer tor the data
1215 * @param msgbuf_size size of the data
1217 * @return 32bit crc value
1221 getcrc32(const char *msgbuf, size_t msgbuf_size)
1223 //TODO calc some crc
1230 * @param msgbuf pointer tor the data
1231 * @param msgbuf_size size of the data
1233 * @return 16bit crc value
1237 getcrc16(const char *msgbuf, size_t msgbuf_size)
1239 //TODO calc some crc
1245 send_hello_beacon(struct Plugin * plugin)
1249 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1254 uint16_t hallo_size;
1255 struct GNUNET_MessageHeader * msgheader;
1256 struct ieee80211_frame * ieeewlanheader;
1257 struct Radiotap_Send * radioHeader;
1258 struct GNUNET_MessageHeader * msgheader2;
1260 hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1261 GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1262 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1263 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1266 msgheader = GNUNET_malloc(size);
1267 msgheader->size = htons(size);
1268 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1270 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1271 getRadiotapHeader(plugin, NULL, radioHeader);
1272 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1273 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin, size);
1275 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1276 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1277 + sizeof(struct GNUNET_MessageHeader));
1279 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1280 memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1282 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1284 if (bytes == GNUNET_SYSERR)
1286 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1287 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1288 errno, strerror(errno));
1291 GNUNET_assert(bytes != GNUNET_SYSERR);
1292 GNUNET_assert(bytes == size);
1293 GNUNET_free(msgheader);
1295 set_next_beacon_time(plugin);
1296 set_next_send(plugin);
1301 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1306 struct GNUNET_MessageHeader * msgheader;
1307 struct ieee80211_frame * ieeewlanheader;
1308 struct Radiotap_Send * radioHeader;
1309 struct FragmentationAckHeader * msgheader2;
1311 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1313 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1314 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1317 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1318 "Sending ack for message_id %u with fragment field %u, size %u\n",
1319 ack->message_id, ack->fragments_field, size
1320 - sizeof(struct Radiotap_Send));
1323 msgheader = GNUNET_malloc(size);
1324 msgheader->size = htons(size);
1325 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1327 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1328 getRadiotapHeader(plugin, ack->session, radioHeader);
1329 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1330 getWlanHeader(ieeewlanheader, &ack->session->addr, plugin, size);
1332 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1333 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1334 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1335 msgheader2->message_id = htonl(ack->message_id);
1336 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1338 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1339 if (bytes == GNUNET_SYSERR)
1341 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1342 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1343 errno, strerror(errno));
1346 GNUNET_assert(bytes != GNUNET_SYSERR);
1347 GNUNET_assert(bytes == size);
1348 GNUNET_free(msgheader);
1349 set_next_send(plugin);
1354 finish_sending(void *cls,
1355 const struct GNUNET_SCHEDULER_TaskContext *tc)
1357 struct Finish_send * finish = cls;
1358 struct Plugin * plugin;
1361 plugin = finish->plugin;
1362 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1364 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1366 GNUNET_free (finish->msgstart);
1367 GNUNET_free (finish);
1370 bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle,
1373 GNUNET_assert (bytes != GNUNET_SYSERR);
1375 if (bytes != finish->size)
1377 finish->msgheader = finish->msgheader + bytes;
1378 finish->size = finish->size - bytes;
1379 plugin->server_write_task
1380 = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
1381 plugin->server_stdin_handle,
1382 &finish_sending, finish);
1386 GNUNET_free(finish->msgstart);
1387 GNUNET_free(finish);
1388 set_next_send(plugin);
1393 * Function called when wlan helper is ready to get some data
1395 * @param cls closure
1396 * @param tc GNUNET_SCHEDULER_TaskContext
1399 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1401 struct Plugin * plugin = cls;
1403 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1404 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1407 struct Session * session;
1408 struct FragmentMessage * fm;
1409 struct ieee80211_frame * ieeewlanheader;
1410 struct Radiotap_Send * radioHeader;
1411 struct GNUNET_MessageHeader * msgheader;
1412 struct FragmentationHeader fragheader;
1413 struct FragmentationHeader * fragheaderptr;
1414 struct Finish_send * finish;
1415 struct AckSendQueue * ack;
1418 const char * copystart;
1421 struct GNUNET_TIME_Absolute next_send;
1423 if (plugin->ack_send_queue_head != NULL)
1425 ack = plugin->ack_send_queue_head;
1426 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1427 plugin->ack_send_queue_tail, ack);
1428 send_ack(plugin, ack);
1433 //test if a "hello-beacon" has to be send
1434 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1436 send_hello_beacon(plugin);
1440 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1444 session = fm->session;
1445 GNUNET_assert(session != NULL);
1447 // test if message timed out
1448 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1451 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1454 free_fragment_message(plugin, fm);
1455 check_fragment_queue(plugin);
1461 //if (fm->message_size > WLAN_MTU)
1463 size = sizeof(struct FragmentationHeader);
1465 set_next_message_fragment_pos(plugin, fm);
1467 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1470 fragheader.fragment_off_or_num = htons(fm->message_pos);
1471 fragheader.message_id = htonl(fm->message_id_out);
1472 copystart = fm->msg + copyoffset;
1473 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1474 WLAN_MTU - sizeof(struct FragmentationHeader));
1478 GNUNET_ERROR_TYPE_DEBUG,
1479 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1480 fm->message_id_out, fm->message_pos, copysize
1481 + sizeof(struct FragmentationHeader), copyoffset,
1482 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1485 if (copyoffset >= fm->message_size)
1488 GNUNET_ERROR_TYPE_ERROR,
1489 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1490 copyoffset, fm->message_size, WLAN_MTU
1491 - sizeof(struct FragmentationHeader), copysize,
1494 GNUNET_assert(copyoffset < fm->message_size);
1496 fragheader.header.size = htons(copysize
1497 + sizeof(struct FragmentationHeader));
1498 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1501 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1502 + sizeof(struct GNUNET_MessageHeader);
1503 msgheader = GNUNET_malloc(size);
1504 msgheader->size = htons(size);
1505 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1507 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1508 getRadiotapHeader(plugin, session, radioHeader);
1510 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1511 getWlanHeader(ieeewlanheader, &(fm->session->addr), plugin, size);
1513 //could be faster if content is just send and not copyed before
1514 //fragmentheader is needed
1515 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1516 memcpy(&ieeewlanheader[1], &fragheader,
1517 sizeof(struct FragmentationHeader));
1518 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1519 memcpy(&fragheaderptr[1], copystart, copysize);
1521 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1523 if (bytes == GNUNET_SYSERR)
1526 GNUNET_ERROR_TYPE_ERROR,
1527 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1528 errno, strerror(errno));
1531 GNUNET_assert(bytes != GNUNET_SYSERR);
1533 //check if this was the last fragment of this message, if true then queue at the end of the list
1534 if (copysize + copyoffset >= fm->message_size)
1536 GNUNET_assert(copysize + copyoffset == fm->message_size);
1538 GNUNET_CONTAINER_heap_update_cost(
1539 plugin->pending_Fragment_Messages, fm->node, MIN(
1540 fm->timeout.abs_value, fm->next_ack.abs_value));
1541 // if fragments have opimized timeouts
1542 //sort_fragment_into_queue(plugin,fm);
1545 #if DEBUG_wlan_retransmission
1547 GNUNET_ERROR_TYPE_DEBUG,
1548 "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1549 fm->message_id_out, fm->message_id_out, fm->message_pos,
1550 fm->message_size, GNUNET_TIME_absolute_get_remaining(
1556 GNUNET_CONTAINER_heap_update_cost(
1557 plugin->pending_Fragment_Messages, fm->node,
1558 GNUNET_TIME_absolute_get().abs_value);
1563 finish = GNUNET_malloc(sizeof( struct Finish_send));
1564 finish->plugin = plugin;
1565 finish->msgheader = (char *) msgheader + bytes;
1566 finish->size = size - bytes;
1567 finish->msgstart = msgheader;
1568 finish ->next_send = next_send;
1570 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1572 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1573 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1574 &finish_sending, finish);
1579 GNUNET_free(msgheader);
1580 set_next_send(plugin);
1587 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1588 "do_transmit did nothing, should not happen!\n");
1592 * Another peer has suggested an address for this
1593 * peer and transport plugin. Check that this could be a valid
1594 * address. If so, consider adding it to the list
1597 * @param cls closure
1598 * @param addr pointer to the address
1599 * @param addrlen length of addr
1600 * @return GNUNET_OK if this is a plausible address for this peer
1604 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1606 //struct Plugin *plugin = cls;
1608 /* check if the address is plausible; if so,
1609 add it to our list! */
1611 GNUNET_assert(cls !=NULL);
1612 //FIXME mitm is not checked
1613 //Mac Address has 6 bytes
1616 /* TODO check for bad addresses like multicast, broadcast, etc */
1620 return GNUNET_SYSERR;
1624 * Function that can be used by the transport service to transmit
1625 * a message using the plugin.
1627 * @param cls closure
1628 * @param target who should receive this message
1629 * @param priority how important is the message
1630 * @param msgbuf the message to transmit
1631 * @param msgbuf_size number of bytes in 'msgbuf'
1632 * @param timeout when should we time out
1633 * @param session which session must be used (or NULL for "any")
1634 * @param addr the address to use (can be NULL if the plugin
1635 * is "on its own" (i.e. re-use existing TCP connection))
1636 * @param addrlen length of the address in bytes
1637 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1638 * otherwise the plugin may use other addresses or
1639 * existing connections (if available)
1640 * @param cont continuation to call once the message has
1641 * been transmitted (or if the transport is ready
1642 * for the next transmission call; or if the
1643 * peer disconnected...)
1644 * @param cont_cls closure for cont
1645 * @return number of bytes used (on the physical network, with overheads);
1646 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1647 * and does NOT mean that the message was not transmitted (DV)
1650 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1651 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1652 struct GNUNET_TIME_Relative timeout, struct Session *session,
1653 const void *addr, size_t addrlen, int force_address,
1654 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1656 struct Plugin * plugin = cls;
1657 struct PendingMessage * newmsg;
1658 struct WlanHeader * wlanheader;
1660 //check if msglen > 0
1661 GNUNET_assert(msgbuf_size > 0);
1663 //get session if needed
1664 if (session == NULL)
1666 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1668 session = get_session(plugin, addr);
1672 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1673 _("Wlan Address len %d is wrong\n"), addrlen);
1678 //TODO target "problem" not solved
1679 //if (session->target != NULL){
1680 // GNUNET_assert(session->target == *target);
1682 session->target = *target;
1688 //queue message in session
1689 //test if there is no other message in the "queue"
1690 //FIXME: to many send requests
1691 //GNUNET_assert (session->pending_message == NULL);
1692 if (session->pending_message != NULL)
1694 newmsg = session->pending_message;
1696 GNUNET_ERROR_TYPE_ERROR,
1697 "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",
1698 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1699 session->fragment_messages_out_count);
1700 if (session->pending_message2 != NULL)
1703 GNUNET_ERROR_TYPE_ERROR,
1704 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1709 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1710 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1711 wlanheader = (struct WlanHeader *) newmsg->msg;
1712 //copy msg to buffer, not fragmented / segmented yet, but with message header
1713 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1714 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1715 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1716 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1717 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1718 newmsg->transmit_cont = cont;
1719 newmsg->transmit_cont_cls = cont_cls;
1720 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1722 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1724 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1726 if (session->pending_message == NULL)
1728 session->pending_message = newmsg;
1732 session->pending_message2 = newmsg;
1736 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1737 "New message for %p with size (incl wlan header) %u added\n", session,
1738 newmsg->message_size);
1742 queue_session(plugin, session);
1744 check_fragment_queue(plugin);
1745 //FIXME not the correct size
1751 * Iterate over the fragment messages of the given session.
1753 * @param cls argument to give to iterator
1754 * @param node node to iterate over
1755 * @param element value stored at the node
1756 * @param cost cost associated with the node
1757 * @return GNUNET_YES if we should continue to iterate,
1761 free_fragment_message_from_session(void *cls,
1762 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1763 GNUNET_CONTAINER_HeapCostType cost)
1765 struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
1766 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1768 if (fm->session == pair->session)
1771 free_fragment_message(pair->plugin, fm);
1778 * Search for fragment message with given id and session
1780 * @param cls argument to give to iterator
1781 * @param node node to iterate over
1782 * @param element value stored at the node
1783 * @param cost cost associated with the node
1784 * @return GNUNET_YES if we should continue to iterate,
1788 search_fragment_message_from_session_and_id(void *cls,
1789 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1790 GNUNET_CONTAINER_HeapCostType cost)
1792 struct Session_id_fragment_triple * triple =
1793 (struct Session_id_fragment_triple *) cls;
1794 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1796 if ((fm->session == triple->session) && (fm->message_id_out
1797 == triple->message_id))
1807 * function to get the message in the fragement queue (out) of a session with a specific id
1808 * @param session pointer to the session
1809 * @param message_id id of the message
1810 * @return pointer to the struct FragmentMessage
1812 static struct FragmentMessage *
1813 get_fragment_message_from_session_and_id(struct Plugin * plugin,
1814 struct Session * session, uint32_t message_id)
1816 struct Session_id_fragment_triple triple;
1817 triple.session = session;
1818 triple.message_id = message_id;
1819 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1820 &search_fragment_message_from_session_and_id, &triple);
1825 * function to get the receive message of a session
1826 * @param plugin pointer to the plugin struct
1827 * @param session session this fragment belongs to
1829 static struct Receive_Message_Queue *
1830 get_receive_message_from_session(struct Plugin * plugin,
1831 struct Session * session)
1833 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1834 while (rec_message != NULL)
1836 if (rec_message->session == session)
1840 rec_message = rec_message->next;
1846 * Function to dispose the fragments received for a message and the message
1847 * @param plugin pointer to the plugin struct
1848 * @param rec_message pointer to the struct holding the message which should be freed
1851 free_receive_message(struct Plugin* plugin,
1852 struct Receive_Message_Queue * rx_message)
1854 GNUNET_assert(rx_message !=NULL);
1855 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1856 struct Receive_Fragment_Queue * rec_queue2;
1858 while (rec_queue != NULL)
1860 rec_queue2 = rec_queue;
1861 rec_queue = rec_queue->next;
1862 GNUNET_free(rec_queue2);
1865 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
1867 GNUNET_assert(plugin->pending_receive_messages > 0);
1868 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
1870 plugin->pending_receive_messages--;
1871 rx_message->session->fragment_messages_in_count--;
1872 GNUNET_free(rx_message);
1876 * function to get the receive message of a session
1877 * @param plugin pointer to the plugin struct
1878 * @param session session this fragment belongs to
1881 check_receive_message_timeouts(struct Plugin * plugin, struct Session * session)
1883 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1884 while (rec_message != NULL)
1886 if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
1889 free_receive_message(plugin, rec_message);
1891 rec_message = rec_message->next;
1898 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
1900 struct Sessionqueue * pendingsession;
1901 struct Sessionqueue * pendingsession_tmp;
1902 struct PendingMessage * pm;
1903 struct Receive_Message_Queue * receive_queue;
1904 struct Plugin_Session_pair pair;
1907 GNUNET_assert(queue != NULL);
1908 GNUNET_assert(queue->content != NULL);
1911 //is this session pending for send
1912 pendingsession = plugin->pending_Sessions_head;
1913 while (pendingsession != NULL)
1915 pendingsession_tmp = pendingsession->next;
1916 if (pendingsession->content == queue->content)
1918 plugin->pendingsessions--;
1919 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1920 plugin->pending_Sessions_tail,
1922 GNUNET_free(pendingsession);
1924 GNUNET_assert (check == 0);
1927 pendingsession = pendingsession_tmp;
1930 //is something of this session in the fragment queue?
1931 pair.plugin = plugin;
1932 pair.session = queue->content;
1933 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1934 &free_fragment_message_from_session, &pair);
1936 //dispose all received fragments
1937 receive_queue = get_receive_message_from_session(plugin, queue->content);
1938 while (receive_queue != NULL)
1940 free_receive_message(plugin, receive_queue);
1941 receive_queue = get_receive_message_from_session(plugin, queue->content);
1944 // remove PendingMessage
1945 pm = queue->content->pending_message;
1948 GNUNET_free_non_null(pm->msg);
1952 // remove PendingMessage
1953 pm = queue->content->pending_message2;
1956 GNUNET_free_non_null(pm->msg);
1960 GNUNET_CONTAINER_DLL_remove(plugin->sessions,
1961 plugin->sessions_tail,
1963 GNUNET_free(queue->content);
1965 plugin->session_count--;
1966 check_fragment_queue(plugin);
1970 * Function that can be used to force the plugin to disconnect
1971 * from the given peer and cancel all previous transmissions
1972 * (and their continuation).
1974 * @param cls closure
1975 * @param target peer from which to disconnect
1978 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1980 struct Plugin *plugin = cls;
1981 struct Sessionqueue * queue = plugin->sessions;
1983 // just look at all the session for the needed one
1984 while (queue != NULL)
1986 // content is never NULL
1987 GNUNET_assert (queue->content != NULL);
1988 if (memcmp(target, &(queue->content->target),
1989 sizeof(struct GNUNET_PeerIdentity)) == 0)
1991 free_session(plugin, queue);
1995 queue = queue->next;
2000 * Convert the transports address to a nice, human-readable
2003 * @param cls closure
2004 * @param type name of the transport that generated the address
2005 * @param addr one of the addresses of the host, NULL for the last address
2006 * the specific address format depends on the transport
2007 * @param addrlen length of the address
2008 * @param numeric should (IP) addresses be displayed in numeric form?
2009 * @param timeout after how long should we give up?
2010 * @param asc function to call on each string
2011 * @param asc_cls closure for asc
2014 wlan_plugin_address_pretty_printer(void *cls, const char *type,
2015 const void *addr, size_t addrlen, int numeric,
2016 struct GNUNET_TIME_Relative timeout,
2017 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
2020 const unsigned char * input;
2022 //GNUNET_assert(cls !=NULL);
2025 /* invalid address (MAC addresses have 6 bytes) */
2030 input = (const unsigned char*) addr;
2031 GNUNET_snprintf(ret, sizeof(ret),
2032 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2033 input[0], input[1], input[2], input[3], input[4], input[5]);
2039 * Function to test if fragment number already exists in the fragments received
2041 * @param rec_message message this fragment belongs to
2042 * @param fh Fragmentheader of the fragment
2043 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2046 is_double_msg(struct Receive_Message_Queue * rx_msg,
2047 struct FragmentationHeader * fh)
2049 //test if bitfield is okay
2051 check_message_fragment_bitfield(rx_msg);
2054 return testBit((char *) &rx_msg->received_fragments, ntohs(
2055 fh->fragment_off_or_num));
2060 * Function to insert a fragment in a queue of a message
2061 * @param session session the fragment belongs to
2062 * @param rec_queue fragment to add
2065 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2066 struct Receive_Fragment_Queue * rx_frag)
2068 GNUNET_assert(rx_message != NULL);
2069 GNUNET_assert(rx_frag != NULL);
2071 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2072 struct WlanHeader * wlanheader;
2074 //this is the first fragment of the message (fragment id 0)
2075 if (rx_frag->num == 0)
2077 wlanheader = (struct WlanHeader *) rx_frag->msg;
2078 rx_message->rec_size = ntohs(wlanheader->header.size);
2082 while (rx_frag2 != NULL)
2084 if (rx_frag2->num > rx_frag->num)
2086 //next element number is grater than the current num
2087 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2088 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2091 rx_frag2 = rx_frag2->next;
2094 //no element has a grater number
2095 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2097 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2101 * handels the data after all fragments are put together
2103 * @param session_light
2104 * @param hdr pointer to the data
2107 wlan_data_message_handler(void *cls, void *client,
2108 const struct GNUNET_MessageHeader *hdr)
2110 struct Plugin * plugin = (struct Plugin*) cls;
2111 struct Session_light * session_light = (struct Session_light *) client;
2112 struct WlanHeader * wlanheader;
2113 struct Session * session;
2114 const char * tempmsg;
2115 const struct GNUNET_MessageHeader * temp_hdr;
2116 struct GNUNET_PeerIdentity tmptarget;
2118 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2123 GNUNET_ERROR_TYPE_DEBUG,
2124 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2128 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2129 + sizeof(struct GNUNET_MessageHeader))
2131 //packet not big enought
2135 GNUNET_assert(session_light != NULL);
2136 if (session_light->session == NULL)
2138 session_light->session = search_session(plugin, &session_light->addr);
2140 session = session_light->session;
2141 wlanheader = (struct WlanHeader *) hdr;
2143 tempmsg = (char*) &wlanheader[1];
2144 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2146 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2149 //wrong crc, dispose message
2150 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2151 "Wlan message Header crc was wrong\n");
2155 //if not in session list
2156 if (session == NULL)
2160 GNUNET_ERROR_TYPE_DEBUG,
2161 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2162 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2163 sizeof(struct WlanHeader));
2165 //try if it is a hello message
2166 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2167 + sizeof(struct WlanHeader))
2169 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2171 if (GNUNET_HELLO_get_id(
2172 (const struct GNUNET_HELLO_Message *) temp_hdr,
2173 &tmptarget) == GNUNET_OK)
2175 session = create_session(plugin, &session_light->addr);
2176 session_light->session = session;
2177 memcpy(&session->target, &tmptarget,
2178 sizeof(struct GNUNET_PeerIdentity));
2182 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2183 "WLAN client not in session list and hello message not okay\n");
2190 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2191 "WLAN client not in session list and not a hello message\n");
2198 GNUNET_ERROR_TYPE_WARNING,
2199 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2200 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2201 sizeof(struct WlanHeader));
2206 //"receive" the message
2209 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2210 (const char *) temp_hdr,
2211 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2217 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2218 "wlan_data_message_handler got wrong message type\n");
2224 * Function to check if all fragments of a message have been received
2225 * @param plugin the plugin handle
2226 * @param session_light information of the message sender
2227 * @param session session the message belongs to
2228 * @param rec_message pointer to the message that should be checked
2232 check_rx_finished_msg(struct Plugin* plugin,
2233 struct Session_light * session_light, struct Session * session,
2234 struct Receive_Message_Queue * rx_message)
2236 GNUNET_assert(rx_message !=NULL);
2238 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2239 int packetsize = rx_message->rec_size;
2243 uint64_t bitfield = 0;
2246 //check if first fragment is present
2247 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2251 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2253 else if (packetsize < sizeof(struct WlanHeader)
2254 + sizeof(struct GNUNET_MessageHeader))
2257 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2259 free_receive_message(plugin, rx_message);
2264 check_message_fragment_bitfield(rx_message);
2267 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2269 bitfield = ~bitfield;
2270 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2271 if (rx_message->received_fragments == bitfield)
2274 while (rx_frag != NULL)
2276 sum += rx_frag->size;
2277 rx_frag = rx_frag->next;
2279 //sum should always be smaller or equal of
2280 GNUNET_assert(sum <= packetsize);
2281 if (sum == packetsize)
2285 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2286 "check_rec_finished_msg: A message for %p is complete\n", session);
2291 //copy fragments together
2292 //msg = GNUNET_malloc(packetsize);
2293 rx_frag = rx_message->frag_head;
2295 /*while (rx_frag != NULL)
2297 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2298 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2299 aktnum += rx_frag->size;
2300 rx_frag = rx_frag->next;
2303 while (rx_frag != NULL)
2305 if (rx_frag->next != NULL)
2307 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2308 session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
2313 //if it is the last fragment just kill all leftover
2314 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2315 session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
2318 rx_frag = rx_frag->next;
2320 free_receive_message(plugin, rx_message);
2321 //call wlan_process_helper to process the message
2322 //wlan_data_message_handler(plugin, session_light,
2323 // (struct GNUNET_MessageHeader*) msg);
2324 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2334 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2337 GNUNET_assert(client != NULL);
2338 GNUNET_assert(cls != NULL);
2339 struct Session * session = (struct Session *) client;
2340 struct Plugin * plugin = (struct Plugin *) cls;
2342 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2343 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2344 distance[0].value = htonl(1);
2345 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2346 distance[1].value = htonl(0);
2349 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2350 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2351 wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
2355 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2356 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2357 (const char*) &session->addr, sizeof(session->addr));
2361 * function to add an ack to send it for a received fragment
2362 * @param plugin pointer to the global plugin structure
2363 * @param session pointer to the session this ack belongs to
2364 * @param bitfield bitfield to send
2365 * @param fh pointer to the fragmentation header which we would like to acknolage
2369 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2370 uint64_t bitfield, struct FragmentationHeader * fh)
2372 struct AckSendQueue * ack;
2374 GNUNET_assert(plugin != NULL);
2375 GNUNET_assert(session != NULL);
2376 GNUNET_assert(fh != NULL);
2378 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2379 ack->fragments_field = bitfield;
2380 ack->message_id = ntohl(fh->message_id);
2381 ack->session = session;
2383 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2384 plugin->ack_send_queue_tail, ack);
2389 * function to get the receive message from the message id and the session
2390 * @param plugin pointer to the plugin struct
2391 * @param session session this fragment belongs to
2392 * @param message_id id of the message
2395 struct Receive_Message_Queue *
2396 get_receive_message(struct Plugin * plugin, struct Session * session,
2397 uint32_t message_id)
2399 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2400 while (rec_message != NULL)
2402 if ((rec_message->message_id_in == message_id) && (rec_message->session
2407 rec_message = rec_message->next;
2413 * function to insert a received fragment into the right fragment queue of the right message
2414 * @param plugin pointer to the plugin struct
2415 * @param session_light pointer to the session_light struct of this message
2416 * @param session session this fragment belongs to
2417 * @param fh pointer to the header of the fragment
2418 * @return new fragment bitfield for the message
2422 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2423 struct Session_light * session_light, struct Session * session,
2424 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2426 struct Receive_Fragment_Queue * rx_frag = NULL;
2427 struct Receive_Message_Queue * rx_message;
2428 const char * tempmsg = (char*) &fh[1];
2429 uint64_t retval = 0;
2431 //TODO fragments do not timeout
2432 //check if message_id is right or it is a new msg
2433 GNUNET_assert(fh != NULL);
2435 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2437 if (rx_message == NULL)
2439 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2441 check_receive_message_timeouts(plugin, session);
2444 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2447 //new message incoming
2448 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2449 rx_message->message_id_in = ntohl(fh->message_id);
2450 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2451 rx_message->session = session;
2452 rx_message->received_fragments = 0;
2454 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2456 session->fragment_messages_in_count++;
2457 plugin->pending_receive_messages++;
2461 GNUNET_ERROR_TYPE_DEBUG,
2462 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2463 rx_message->message_id_in, session->fragment_messages_in_count,
2464 plugin->pending_receive_messages);
2471 GNUNET_ERROR_TYPE_INFO,
2472 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
2473 get_receive_message_from_session(plugin, session)->message_id_in);
2474 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2480 rx_message->timeout = GNUNET_TIME_absolute_add(
2481 GNUNET_TIME_absolute_get(),
2482 MESSAGE_IN_TIMEOUT);
2484 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2488 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2489 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2490 rx_frag->size = ntohs(fh->header.size)
2491 - sizeof(struct FragmentationHeader);
2492 rx_frag->num = ntohs(fh->fragment_off_or_num);
2493 rx_frag->msg = (char*) &(rx_frag[1]);
2494 //copy msg to buffer
2495 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2496 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2497 insert_fragment_in_queue(rx_message, rx_frag);
2499 retval = rx_message->received_fragments;
2503 GNUNET_ERROR_TYPE_DEBUG,
2504 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2505 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2506 rx_message->received_fragments, session);
2509 check_rx_finished_msg(plugin, session_light, session, rx_message);
2513 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2514 retval = rx_message->received_fragments;
2522 * Function used for to process the data received from the wlan interface
2524 * @param cls the plugin handle
2525 * @param session_light FIXME: document
2526 * @param hdr hdr of the GNUNET_MessageHeader
2529 wlan_data_helper(void *cls, struct Session_light * session_light,
2530 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2532 struct Plugin *plugin = cls;
2533 struct Session * session;
2535 struct FragmentationHeader * fh;
2536 struct FragmentationAckHeader * fah;
2537 struct FragmentMessage * fm;
2539 const char * tempmsg;
2541 uint64_t fragment_bitfield = 0;
2544 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2547 //TODO better DOS protection, error handling
2548 //TODO test first than create session
2549 GNUNET_assert(session_light != NULL);
2553 GNUNET_ERROR_TYPE_DEBUG,
2554 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2555 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2556 session_light->addr.mac, 6));
2559 if (session_light->session == NULL)
2561 session_light->session = get_session(plugin, &session_light->addr);
2563 GNUNET_assert(GNUNET_HELLO_get_id(
2564 (const struct GNUNET_HELLO_Message *) &hdr[1],
2565 &(session_light->session->target) ) != GNUNET_SYSERR);
2571 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2574 GNUNET_assert(session_light != NULL);
2575 if (session_light->session == NULL)
2577 session_light->session = search_session(plugin, &session_light->addr);
2579 session = session_light->session;
2581 fh = (struct FragmentationHeader *) hdr;
2582 tempmsg = (char*) &fh[1];
2586 GNUNET_ERROR_TYPE_DEBUG,
2587 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2588 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2589 hdr->size), wlan_plugin_address_to_string(NULL,
2590 session_light->addr.mac, 6));
2593 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2595 //wrong crc, dispose message
2596 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2600 //if in the session list
2601 if (session != NULL)
2603 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2604 session_light, session, fh, rxinfo);
2610 GNUNET_ERROR_TYPE_INFO,
2611 "WLAN client not in session list, fragment num %u, message id %u\n",
2612 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2614 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
2615 tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
2616 GNUNET_YES, GNUNET_NO);
2617 //wlan_data_message_handler(plugin, session_light,
2618 // (struct GNUNET_MessageHeader *) tempmsg);
2619 session = session_light->session;
2620 //test if a session was created
2621 if (session == NULL)
2625 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2628 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2629 set_next_send(plugin);
2635 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2640 GNUNET_ERROR_TYPE_DEBUG,
2641 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2642 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2643 session_light->addr.mac, 6));
2646 GNUNET_assert(session_light != NULL);
2647 if (session_light->session == NULL)
2649 session_light->session = search_session(plugin, &session_light->addr);
2650 GNUNET_assert(session_light->session != NULL);
2652 session = session_light->session;
2653 fah = (struct FragmentationAckHeader *) hdr;
2654 fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
2660 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
2661 fah->fragment_field);
2662 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
2664 #if DEBUG_wlan_retransmission
2665 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
2666 fm->message_id_out, fm->ack_bitfield);
2668 check_finished_fragment(plugin, fm);
2669 set_next_send(plugin);
2674 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2675 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2685 GNUNET_ERROR_TYPE_INFO,
2686 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2687 ntohs(hdr->type), ntohs(hdr->size));
2693 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2694 "Helper finished\n");
2701 macprinter(const u_int8_t * mac)
2703 static char macstr[20];
2705 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2706 mac[2], mac[3], mac[4], mac[5]);
2711 * Function used for to process the data from the suid process
2713 * @param cls the plugin handle
2714 * @param client client that send the data (not used)
2715 * @param hdr header of the GNUNET_MessageHeader
2718 wlan_process_helper(void *cls, void *client,
2719 const struct GNUNET_MessageHeader *hdr)
2721 struct Plugin *plugin = cls;
2722 struct ieee80211_frame * wlanIeeeHeader = NULL;
2723 struct Session_light * session_light = NULL;
2724 struct Radiotap_rx * rxinfo;
2725 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2730 switch (ntohs(hdr->type))
2732 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2735 GNUNET_ERROR_TYPE_DEBUG,
2736 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2740 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2741 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2742 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2745 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2746 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2747 hdr->size), sizeof(struct ieee80211_frame)
2748 + sizeof(struct GNUNET_MessageHeader));
2751 /* FIXME: restart SUID process */
2754 rxinfo = (struct Radiotap_rx *) &hdr[1];
2755 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2757 //process only if it is an broadcast or for this computer both with the gnunet bssid
2760 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
2761 sizeof(struct MacAddress)) == 0)
2763 //check for broadcast or mac
2764 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2765 sizeof(struct MacAddress) == 0) || memcmp(
2766 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2767 sizeof(struct MacAddress)) == 0)
2770 // process the inner data
2773 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2774 - sizeof(struct GNUNET_MessageHeader)
2775 - sizeof(struct Radiotap_rx);
2777 session_light = GNUNET_malloc(sizeof(struct Session_light));
2778 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2779 sizeof(struct MacAddress));
2780 //session_light->session = search_session(plugin,session_light->addr);
2783 while (pos < datasize)
2785 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2788 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2789 pos += ntohs(temp_hdr->size);
2794 GNUNET_free(session_light);
2799 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2800 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2801 wlanIeeeHeader->i_addr1));
2808 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2809 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2810 wlanIeeeHeader->i_addr2));
2814 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2815 //TODO more control messages
2816 //TODO use struct wlan_helper_control
2817 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2820 /* FIXME: restart SUID process */
2823 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2825 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2826 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2827 wlan_plugin_address_to_string(cls, &plugin->mac_address,
2828 sizeof(struct MacAddress)));
2830 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2831 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2840 * We have been notified that wlan-helper has written something to stdout.
2841 * Handle the output, then reschedule this function to be called again once
2842 * more is available.
2844 * @param cls the plugin handle
2845 * @param tc the scheduling context
2848 wlan_plugin_helper_read(void *cls,
2849 const struct GNUNET_SCHEDULER_TaskContext *tc)
2851 struct Plugin *plugin = cls;
2852 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2854 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2857 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2860 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2865 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2866 _("Finished reading from wlan-helper stdout with code: %d\n"),
2871 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2872 GNUNET_NO, GNUNET_NO);
2874 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2875 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2876 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2877 &wlan_plugin_helper_read, plugin);
2881 * Start the gnunet-wlan-helper process.
2883 * @param plugin the transport plugin
2884 * @param testmode should we use the dummy driver for testing?
2885 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2888 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2890 const char * filename = "gnunet-transport-wlan-helper";
2891 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2892 if (plugin->server_stdout == NULL)
2893 return GNUNET_SYSERR;
2895 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2896 if (plugin->server_stdin == NULL)
2897 return GNUNET_SYSERR;
2900 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2901 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2902 plugin->interface, testmode);
2904 /* Start the server process */
2906 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2907 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2908 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2909 if (plugin->server_proc == NULL)
2912 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2913 "Failed to start gnunet-wlan-helper process\n");
2915 return GNUNET_SYSERR;
2918 /* Close the write end of the read pipe */
2919 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2921 /* Close the read end of the write pipe */
2922 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2924 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2925 GNUNET_DISK_PIPE_END_READ);
2926 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2927 GNUNET_DISK_PIPE_END_WRITE);
2929 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2932 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2933 "Adding server_read_task for the wlan-helper\n");
2936 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2937 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2938 &wlan_plugin_helper_read, plugin);
2944 * Exit point from the plugin.
2945 * @param cls pointer to the api struct
2950 libgnunet_plugin_transport_wlan_done(void *cls)
2952 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2953 struct Plugin *plugin = api->cls;
2954 struct Sessionqueue * queue = plugin->sessions;
2955 struct Sessionqueue * queue_next;
2956 struct FragmentMessage * fm;
2959 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2960 "libgnunet_plugin_transport_wlan_done started\n");
2964 GNUNET_OS_process_close(plugin->server_proc);
2965 GNUNET_DISK_pipe_close(plugin->server_stdout);
2966 GNUNET_DISK_pipe_close(plugin->server_stdin);
2968 GNUNET_assert (cls !=NULL);
2970 while (queue != NULL)
2972 queue_next = queue->next;
2973 free_session(plugin, queue);
2977 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
2979 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
2980 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2982 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
2984 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
2985 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2987 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
2989 GNUNET_SCHEDULER_cancel(plugin->server_read_task);
2990 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2994 if (plugin->suid_tokenizer != NULL)
2995 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2997 if (plugin->data_tokenizer != NULL)
2998 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3000 if (plugin->fragment_tokenizer != NULL)
3001 GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
3003 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3004 plugin->pending_Fragment_Messages);
3008 free_fragment_message(plugin, fm);
3009 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3010 plugin->pending_Fragment_Messages);
3013 GNUNET_free_non_null(plugin->interface);
3014 GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
3015 GNUNET_free (plugin);
3021 * Entry point for the plugin.
3023 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3024 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3027 libgnunet_plugin_transport_wlan_init(void *cls)
3029 //struct GNUNET_SERVICE_Context *service;
3030 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3031 struct GNUNET_TRANSPORT_PluginFunctions *api;
3032 struct Plugin *plugin;
3033 static unsigned long long testmode = 0;
3035 GNUNET_assert(cls !=NULL);
3037 plugin = GNUNET_malloc (sizeof (struct Plugin));
3039 plugin->pendingsessions = 0;
3040 plugin->session_count = 0;
3041 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3042 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3043 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3044 plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
3045 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3047 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3050 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3051 plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
3052 &wlan_data_message_handler, plugin);
3054 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3055 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3057 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3059 api->send = &wlan_plugin_send;
3060 api->disconnect = &wlan_plugin_disconnect;
3061 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3062 api->check_address = &wlan_plugin_address_suggested;
3063 api->address_to_string = &wlan_plugin_address_to_string;
3067 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3069 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3070 "transport-wlan", "TESTMODE", &testmode))
3071 testmode = 0; //default value
3074 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3076 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3077 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3079 libgnunet_plugin_transport_wlan_done(api);
3085 set_next_beacon_time(plugin);
3087 wlan_transport_start_wlan_helper(plugin, testmode);
3090 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3096 /* end of plugin_transport_wlan.c */