2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/plugin_transport_wlan.c
23 * @brief transport plugin for wlan
24 * @author David Brodski
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
37 #include "wlan/ieee80211.h"
41 #define PROTOCOL_PREFIX "wlan"
44 * Max size of packet from helper
49 * Time until retransmission of a fragment in ms
51 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
53 #define FRAGMENT_QUEUE_SIZE 10
54 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
56 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
58 #define MESSAGES_IN_QUEUE_SIZE 10
59 #define MESSAGES_IN_QUEUE_PER_SESSION 1
61 #define HALLO_BEACON_SCALING_FACTOR 900
63 #define DEBUG_wlan GNUNET_NO
65 #define MESSAGE_LENGHT_UNKNOWN -1
66 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
69 * After how long do we expire an address that we
70 * learned from another peer if it is not reconfirmed
73 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
76 * Initial handshake message for a session.
81 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
83 struct GNUNET_MessageHeader header;
86 * Identit*mac_y of the node connecting (TCP client)
88 struct GNUNET_PeerIdentity clientIdentity;
93 * Encapsulation of all of the state of the plugin.
100 struct GNUNET_TRANSPORT_PluginEnvironment *env;
103 * List of open sessions. head
105 struct Sessionqueue *sessions;
108 * List of open sessions. tail
110 struct Sessionqueue *sessions_tail;
119 * encapsulation of data from the local wlan helper program
122 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
125 * encapsulation of packets received
128 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
131 * stdout pipe handle for the gnunet-wlan-helper process
133 struct GNUNET_DISK_PipeHandle *server_stdout;
136 * stdout file handle for the gnunet-wlan-helper process
138 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
141 * stdin pipe handle for the gnunet-wlan-helper process
143 struct GNUNET_DISK_PipeHandle *server_stdin;
146 * stdin file handle for the gnunet-wlan-helper process
148 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
151 * ID of the gnunet-wlan-server std read task
153 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
156 * ID of the gnunet-wlan-server std read task
158 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
161 * ID of the delay task for writing
163 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
166 * The process id of the wlan process
168 struct GNUNET_OS_Process *server_proc;
171 * The interface of the wlan card given to us by the user.
176 * The mac_address of the wlan card given to us by the helper.
178 struct MacAddress mac_address;
181 * Sessions currently pending for transmission
182 * to this peer, if any.
184 struct Sessionqueue * pending_Sessions;
187 * Sessions currently pending for transmission
188 * to this peer (tail), if any.
190 struct Sessionqueue * pending_Sessions_tail;
193 * number of pending sessions
195 unsigned int pendingsessions;
198 * Messages in the fragmentation queue, head
201 struct FragmentMessage * pending_Fragment_Messages_head;
204 * Messages in the fragmentation queue, tail
207 struct FragmentMessage * pending_Fragment_Messages_tail;
210 * number of pending fragment message
213 unsigned int pending_fragment_messages;
216 * Messages in the in Queue, head
219 struct Receive_Message_Queue * receive_messages_head;
222 * Messages in the in Queue, tail
225 struct Receive_Message_Queue * receive_messages_teil;
228 * number of messages in the in queue
231 unsigned int pending_receive_messages;
234 * time of the next "hello-beacon"
237 struct GNUNET_TIME_Absolute beacon_time;
240 * queue to send acks for received fragments (head)
243 struct AckSendQueue * ack_send_queue_head;
246 * queue to send acks for received fragments (tail)
249 struct AckSendQueue * ack_send_queue_tail;
254 * Struct to store data if file write did not accept the whole packet
258 struct Plugin * plugin;
260 struct GNUNET_MessageHeader * msgstart;
265 * Queue of sessions, for the general session queue and the pending session queue
270 struct Sessionqueue * next;
271 struct Sessionqueue * prev;
272 struct Session * content;
276 * Queue for the fragments received
279 struct Receive_Fragment_Queue
281 struct Receive_Fragment_Queue * next;
282 struct Receive_Fragment_Queue * prev;
286 struct Radiotap_rx rxinfo;
290 * Queue for the fragments received
293 struct Receive_Message_Queue
295 struct Receive_Message_Queue * next;
297 struct Receive_Message_Queue * prev;
300 * current number for message incoming, to distinguish between the messages
302 uint32_t message_id_in;
305 * size of the message received,
306 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
307 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
313 * Sorted queue with the fragments received; head
316 struct Receive_Fragment_Queue * frag_head;
319 * Sorted queue with the fragments received; tail
322 struct Receive_Fragment_Queue * frag_tail;
325 * Session this fragment belongs to
328 struct Session * session;
331 * Timeout value for the pending message.
333 struct GNUNET_TIME_Absolute timeout;
336 * Bitfield of received fragments
339 uint64_t received_fragments;
343 * Information kept for each message that is yet to
346 struct PendingMessage
350 * The pending message
355 * Size of the message
360 * Continuation function to call once the message
361 * has been sent. Can be NULL if there is no
362 * continuation to call.
364 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
367 * Cls for transmit_cont
369 void * transmit_cont_cls;
372 * Timeout value for the pending message.
374 struct GNUNET_TIME_Absolute timeout;
379 * Queue for acks to send for fragments recived
385 struct AckSendQueue * next;
386 struct AckSendQueue * prev;
388 struct Session * session;
390 * ID of message, to distinguish between the messages, picked randomly.
395 * Bit field for received fragments
397 uint64_t fragments_field;
402 * Session infos gathered from a messages
408 * the session this message belongs to
410 struct Session * session;
418 * Session handle for connections.
426 struct SessionHeader header;
429 * Pointer to the global plugin struct.
431 struct Plugin *plugin;
434 * Message currently pending for transmission
435 * to this peer, if any.
437 struct PendingMessage *pending_message;
440 * Message currently pending for transmission
441 * to this peer, if any.
443 struct PendingMessage *pending_message2;
446 * To whom are we talking to (set to our identity
447 * if we are still waiting for the welcome message)
449 struct GNUNET_PeerIdentity target;
457 * Address of the other peer (either based on our 'connect'
458 * call or on our 'accept' call).
463 * Last activity on this connection. Used to select preferred
466 struct GNUNET_TIME_Absolute last_activity;
469 * count of messages in the fragment out queue for this session
472 int fragment_messages_out_count;
475 * count of messages in the fragment in queue for this session
478 int fragment_messages_in_count;
488 * Struct for Messages in the fragment queue
491 struct FragmentMessage
494 * Session this message belongs to
497 struct Session *session;
500 * This is a doubly-linked list.
502 struct FragmentMessage *next;
505 * This is a doubly-linked list.
507 struct FragmentMessage *prev;
510 * The pending message
515 * Timeout value for the pending message.
517 struct GNUNET_TIME_Absolute timeout;
520 * Timeout value for the pending fragments.
521 * Stores the time when the next msg fragment ack has to be received
523 struct GNUNET_TIME_Absolute next_ack;
526 * bitfield with all acks received for this message
528 uint64_t ack_bitfield;
531 * Size of the message
536 * pos / next fragment number in the message, for fragmentation/segmentation,
537 * some acks can be missing but there is still time
539 uint32_t message_pos;
542 * current number for message outgoing, to distinguish between the messages
544 uint32_t message_id_out;
548 * Header for messages which need fragmentation
550 struct FragmentationAckHeader
553 struct GNUNET_MessageHeader header;
556 * ID of message, to distinguish between the messages, picked randomly.
558 uint32_t message_id GNUNET_PACKED;
561 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
563 uint64_t fragment_field GNUNET_PACKED;
568 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
569 struct Radiotap_Send * Header);
572 getWlanHeader(struct ieee80211_frame * Header, const char * to_mac_addr,
573 struct Plugin * plugin);
576 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
579 getcrc16(const char *msgbuf, size_t msgbuf_size);
582 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
585 check_fragment_queue(struct Plugin * plugin);
588 getcrc32(const char *msgbuf, size_t msgbuf_size);
591 free_receive_message(struct Plugin* plugin,
592 struct Receive_Message_Queue * rx_message);
594 struct Receive_Message_Queue *
595 get_receive_message_from_session(struct Plugin * plugin,
596 struct Session * session);
599 wlan_data_helper(void *cls, struct Session_light * session_light,
600 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo);
603 wlan_process_helper(void *cls, void *client,
604 const struct GNUNET_MessageHeader *hdr);
607 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
610 wlan_data_massage_handler(struct Plugin * plugin,
611 struct Session_light * session_light,
612 const struct GNUNET_MessageHeader * hdr);
615 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen);
617 struct Receive_Message_Queue *
618 get_receive_message(struct Plugin * plugin, struct Session * session,
619 uint32_t message_id);
622 htonll(uint64_t input)
628 ntohll(uint64_t input)
634 * Sets a bit active in the bitArray. Increment bit-specific
635 * usage counter on disk only if below 4bit max (==15).
637 * @param bitArray memory area to set the bit in
638 * @param bitIdx which bit to set
641 setBit(char *bitArray, unsigned int bitIdx)
644 unsigned int targetBit;
646 arraySlot = bitIdx / 8;
647 targetBit = (1L << (bitIdx % 8));
648 bitArray[arraySlot] |= targetBit;
652 * Clears a bit from bitArray. Bit is cleared from the array
653 * only if the respective usage counter on the disk hits/is zero.
655 * @param bitArray memory area to set the bit in
656 * @param bitIdx which bit to unset
659 clearBit(char *bitArray, unsigned int bitIdx)
662 unsigned int targetBit;
665 targetBit = (1L << (bitIdx % 8));
666 bitArray[slot] = bitArray[slot] & (~targetBit);
670 * Checks if a bit is active in the bitArray
672 * @param bitArray memory area to set the bit in
673 * @param bitIdx which bit to test
674 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
677 testBit(char *bitArray, unsigned int bitIdx)
680 unsigned int targetBit;
683 targetBit = (1L << (bitIdx % 8));
684 if (bitArray[slot] & targetBit)
691 * get the next message number, at the moment just a random one
692 * @return returns the next valid message-number for sending packets
695 get_next_message_id()
697 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
701 * start next message number generator
702 * (not necessary at the moment)
705 start_next_message_id()
707 //GNUNET_CRYPTO_random_init;
711 * search for a session with the addr
713 * @param plugin pointer to the plugin struct
714 * @param addr pointer to the mac address of the peer
715 * @return returns the session
718 static struct Session *
719 search_session(struct Plugin *plugin, const uint8_t * addr)
721 struct Sessionqueue * queue = plugin->sessions;
722 struct Sessionqueue * lastitem = NULL;
724 //just look at all the session for the needed one
725 while (queue != NULL)
727 // content is never NULL
728 GNUNET_assert (queue->content != NULL);
729 char * addr2 = queue->content->addr;
730 if (memcmp(addr, addr2, 6) == 0)
733 return queue->content;
743 * create a new session
745 * @param plugin pointer to the plugin struct
746 * @param addr pointer to the mac address of the peer
747 * @return returns the session
750 static struct Session *
751 create_session(struct Plugin *plugin, const uint8_t * addr)
753 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
755 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
757 queue->content = GNUNET_malloc (sizeof (struct Session));
758 queue->content->plugin = plugin;
759 memcpy(queue->content->addr, addr, 6);
760 queue->content->fragment_messages_out_count = 0;
761 queue->content->fragment_messages_in_count = 0;
763 plugin->session_count++;
766 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
767 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
770 return queue->content;
774 * get Session from address, create if no session exists
776 * @param plugin pointer to the plugin struct
777 * @param addr pointer to the mac address of the peer
778 * @return returns the session
780 //TODO add other possibilities to find the right session (are there other?)
781 static struct Session *
782 get_Session(struct Plugin *plugin, const uint8_t * addr)
784 struct Session * session = search_session(plugin, addr);
790 return create_session(plugin, addr);
792 /* -- not needed, layer above already has it--
793 //queue welcome message for new sessions, not realy needed
794 //struct WelcomeMessage welcome;
795 struct PendingMessage *pm;
796 pm = GNUNET_malloc (sizeof (struct PendingMessage));
797 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
798 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
799 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
800 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
801 //welcome.clientIdentity = *plugin->env->my_identity;
802 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
803 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
804 queue->content->pending_message = pm;
805 plugin->pendingsessions ++;
806 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
808 check_fragment_queue(plugin);
813 * Queue the session to send data
817 queue_Session(struct Plugin *plugin, struct Session * session)
819 struct Sessionqueue * queue = plugin->pending_Sessions;
820 struct Sessionqueue * lastitem = NULL;
822 while (queue != NULL)
824 // content is never NULL
825 GNUNET_assert (queue->content != NULL);
826 // is session already in queue?
827 if (session == queue->content)
836 // Session is not in the queue
838 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
839 queue->content = session;
842 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
843 plugin->pending_Sessions_tail,
844 plugin->pending_Sessions_tail, queue);
845 plugin->pendingsessions++;
851 * Function to schedule the write task, executed after a delay
854 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
856 struct Plugin * plugin = cls;
857 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
859 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
862 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
863 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
865 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
866 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
867 &do_transmit, plugin);
873 * Function to calculate the time of the next periodic "hello-beacon"
876 set_next_beacon_time(struct Plugin * const plugin)
878 //under 10 known peers: once a second
879 if (plugin->session_count < 10)
881 plugin->beacon_time = GNUNET_TIME_absolute_add(
882 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
883 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
885 //under 30 known peers: every 10 seconds
886 else if (plugin->session_count < 30)
888 plugin->beacon_time = GNUNET_TIME_absolute_add(
889 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
890 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
892 //over 30 known peers: once a minute
895 plugin->beacon_time = GNUNET_TIME_absolute_add(
896 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
897 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
902 struct GNUNET_TIME_Relative
903 get_next_frag_timeout(struct FragmentMessage * fm)
905 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
906 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
911 * Function to get the timeout value for acks for this session
914 struct GNUNET_TIME_Relative
915 get_ack_timeout(struct FragmentMessage * fm)
917 return FRAGMENT_TIMEOUT;
921 * Function to set the timer for the next timeout of the fragment queue
922 * @param plugin the handle to the plugin struct
925 check_next_fragment_timeout(struct Plugin * const plugin)
927 struct FragmentMessage * fm;
928 struct GNUNET_TIME_Relative next_send;
931 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
933 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
934 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
936 fm = plugin->pending_Fragment_Messages_head;
938 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
940 //check if some acks are in the queue
941 if (plugin->ack_send_queue_head != NULL)
943 next_send = GNUNET_TIME_UNIT_ZERO;
945 //check if there are some fragments in the queue
948 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
951 next_send = GNUNET_TIME_relative_min(next_send,
952 get_next_frag_timeout(fm));
955 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
956 &delay_fragment_task, plugin);
961 * Function to get the next queued Session, removes the session from the queue
964 static struct Session *
965 get_next_queue_Session(struct Plugin * plugin)
967 struct Session * session;
968 struct Sessionqueue * sessionqueue;
969 struct Sessionqueue * sessionqueue_alt;
970 struct PendingMessage * pm;
971 sessionqueue = plugin->pending_Sessions;
972 while (sessionqueue != NULL)
974 session = sessionqueue->content;
976 pm = session->pending_message;
980 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
981 "pending message is empty, should not happen. session %p\n",
985 GNUNET_assert(pm != NULL);
987 //check for message timeout
988 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
990 //check if session has no message in the fragment queue
991 if (session->fragment_messages_out_count
992 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
994 plugin->pendingsessions--;
995 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
996 plugin->pending_Sessions_tail, sessionqueue);
997 GNUNET_free(sessionqueue);
1003 sessionqueue = sessionqueue->next;
1009 session->pending_message = session->pending_message2;
1010 session->pending_message2 = NULL;
1012 //call the cont func that it did not work
1013 if (pm->transmit_cont != NULL)
1014 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1016 GNUNET_free(pm->msg);
1019 if (session->pending_message == NULL)
1021 sessionqueue_alt = sessionqueue;
1022 sessionqueue = sessionqueue->next;
1023 plugin->pendingsessions--;
1024 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1025 plugin->pending_Sessions_tail, sessionqueue_alt);
1027 GNUNET_free(sessionqueue_alt);
1037 * Function to sort the message into the message fragment queue
1038 * @param plugin the plugin struct
1039 * @param fm message to sort into the queue
1042 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
1044 struct FragmentMessage * fm2;
1045 //sort into the list at the right position
1047 fm2 = plugin->pending_Fragment_Messages_head;
1051 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
1054 GNUNET_CONTAINER_DLL_insert_before(plugin->pending_Fragment_Messages_head,
1055 plugin->pending_Fragment_Messages_tail,fm2,fm);
1064 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1065 plugin->pending_Fragment_Messages_tail,fm);
1069 * frees the space of a message in the fragment queue (send queue)
1070 * @param plugin the plugin struct
1071 * @param fm message to free
1074 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1078 (fm->session->fragment_messages_out_count)--;
1079 GNUNET_free_non_null(fm->msg);
1080 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1081 plugin->pending_Fragment_Messages_tail, fm);
1083 plugin->pending_fragment_messages--;
1086 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1087 "free pending fragment messages, pending messages remaining %u\n",
1088 plugin->pending_fragment_messages);
1094 * Function to check if there is some space in the fragment queue
1095 * inserts a message if space is available
1096 * @param plugin the plugin struct
1100 check_fragment_queue(struct Plugin * plugin)
1102 struct Session * session;
1103 struct FragmentMessage * fm;
1104 struct GNUNET_PeerIdentity pid;
1106 struct PendingMessage * pm;
1108 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
1110 session = get_next_queue_Session(plugin);
1111 if (session != NULL)
1113 pm = session->pending_message;
1114 session->pending_message = NULL;
1115 session->fragment_messages_out_count++;
1116 GNUNET_assert(pm != NULL);
1118 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1119 fm->message_size = pm->message_size;
1121 fm->session = session;
1122 fm->timeout.abs_value = pm->timeout.abs_value;
1123 fm->message_pos = 0;
1124 fm->next_ack = GNUNET_TIME_absolute_get();
1125 fm->message_id_out = get_next_message_id();
1126 fm->ack_bitfield = 0;
1128 sort_fragment_into_queue(plugin, fm);
1129 plugin->pending_fragment_messages++;
1131 if (pm->transmit_cont != NULL)
1133 pid = session->target;
1134 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1136 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1137 "called pm->transmit_cont for %p\n", session);
1143 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1144 "no pm->transmit_cont for %p\n", session);
1149 if (session->pending_message2 != NULL)
1151 session->pending_message = session->pending_message2;
1152 session->pending_message2 = NULL;
1154 queue_Session(plugin, session);
1157 //check if timeout changed
1158 check_next_fragment_timeout(plugin);
1164 * Funktion to check if all fragments where send and the acks received
1165 * frees the space if finished
1166 * @param plugin the plugin struct
1167 * @param fm the message to check
1170 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1172 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1173 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1174 - sizeof(struct FragmentationHeader)));
1175 uint64_t tmpfield = UINT64_MAX;
1176 tmpfield = tmpfield >> maxack;
1180 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1181 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1182 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1185 if (fm->ack_bitfield == tmpfield)
1188 free_fragment_message(plugin, fm);
1191 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1192 "Finished sending and got all acks for a fragmented message\n");
1195 check_next_fragment_timeout(plugin);
1196 check_fragment_queue(plugin);
1202 * Function to set the next fragment number
1203 * @param fm use this FragmentMessage
1207 set_next_message_fragment_pos(struct FragmentMessage * fm)
1210 //check if retransmit is needed
1211 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1214 // be positive and try again later :-D
1215 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1216 // find first missing fragment
1218 fm->message_pos = 0;
1221 //test if ack 0 (or X) was already received
1222 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1230 send_hello_beacon(struct Plugin * plugin)
1234 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1239 struct GNUNET_MessageHeader * msgheader = NULL;
1240 struct ieee80211_frame * ieeewlanheader = NULL;
1241 struct Radiotap_Send * radioHeader = NULL;
1242 struct GNUNET_MessageHeader * msgheader2 = NULL;
1244 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1245 *(plugin->env->our_hello)) <= WLAN_MTU);
1246 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1247 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1248 + GNUNET_HELLO_size(*(plugin->env->our_hello));
1250 msgheader = GNUNET_malloc(size);
1251 msgheader->size = htons(size);
1252 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1254 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1255 getRadiotapHeader(plugin, NULL, radioHeader);
1256 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1257 getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
1259 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1260 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1261 + sizeof(struct GNUNET_MessageHeader));
1263 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1264 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1265 *(plugin->env->our_hello)));
1267 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1269 if (bytes == GNUNET_SYSERR)
1271 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1272 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1273 errno, strerror(errno));
1276 GNUNET_assert(bytes != GNUNET_SYSERR);
1277 GNUNET_assert(bytes == size);
1278 GNUNET_free(msgheader);
1280 set_next_beacon_time(plugin);
1281 check_next_fragment_timeout(plugin);
1285 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1290 struct GNUNET_MessageHeader * msgheader = NULL;
1291 struct ieee80211_frame * ieeewlanheader = NULL;
1292 struct Radiotap_Send * radioHeader = NULL;
1293 struct FragmentationAckHeader * msgheader2 = NULL;
1295 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1297 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1298 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1301 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1302 "Sending ack for message_id %u with fragment field %u, size %u\n",
1303 ack->message_id, ack->fragments_field, size
1304 - sizeof(struct Radiotap_Send));
1307 msgheader = GNUNET_malloc(size);
1308 msgheader->size = htons(size);
1309 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1311 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1312 getRadiotapHeader(plugin, ack->session, radioHeader);
1313 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1314 getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
1316 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1317 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1318 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1319 msgheader2->message_id = htonl(ack->message_id);
1320 msgheader2->fragment_field = htonll(ack->fragments_field);
1322 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1323 if (bytes == GNUNET_SYSERR)
1325 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1326 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1327 errno, strerror(errno));
1330 GNUNET_assert(bytes != GNUNET_SYSERR);
1331 GNUNET_assert(bytes == size);
1332 GNUNET_free(msgheader);
1333 check_next_fragment_timeout(plugin);
1337 * Function called when wlan helper is ready to get some data
1339 * @param cls closure
1340 * @param tc GNUNET_SCHEDULER_TaskContext
1344 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1347 struct Plugin * plugin = cls;
1348 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1350 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1353 struct Session * session = NULL;
1354 struct FragmentMessage * fm = NULL;
1355 struct ieee80211_frame * ieeewlanheader = NULL;
1356 struct Radiotap_Send * radioHeader = NULL;
1357 struct GNUNET_MessageHeader * msgheader = NULL;
1359 struct FragmentationHeader fragheader;
1360 struct FragmentationHeader * fragheaderptr = NULL;
1361 struct Finish_send * finish = NULL;
1362 struct AckSendQueue * ack;
1365 const char * copystart = NULL;
1366 uint16_t copysize = 0;
1367 uint copyoffset = 0;
1369 if (plugin->ack_send_queue_head != NULL)
1371 ack = plugin->ack_send_queue_head;
1372 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1373 plugin->ack_send_queue_tail, ack);
1374 send_ack(plugin, ack);
1379 //test if a "hello-beacon" has to be send
1380 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1382 send_hello_beacon(plugin);
1388 fm = plugin->pending_Fragment_Messages_head;
1391 session = fm->session;
1392 GNUNET_assert(session != NULL);
1394 // test if message timed out
1395 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1398 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1401 check_fragment_queue(plugin);
1402 free_fragment_message(plugin, fm);
1408 //if (fm->message_size > WLAN_MTU)
1410 size = sizeof(struct FragmentationHeader);
1412 set_next_message_fragment_pos(fm);
1414 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1419 fragheader.fragment_off_or_num = htons(fm->message_pos);
1420 fragheader.message_id = htonl(fm->message_id_out);
1421 copystart = fm->msg + copyoffset;
1422 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1423 WLAN_MTU - sizeof(struct FragmentationHeader));
1427 GNUNET_ERROR_TYPE_DEBUG,
1428 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1429 fm->message_id_out, fm->message_pos, copysize
1430 + sizeof(struct FragmentationHeader), copyoffset,
1431 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1434 if (copyoffset >= fm->message_size)
1437 GNUNET_ERROR_TYPE_ERROR,
1438 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1439 copyoffset, fm->message_size, WLAN_MTU
1440 - sizeof(struct FragmentationHeader), copysize,
1443 GNUNET_assert(copyoffset < fm->message_size);
1444 //FIXME remove later
1445 GNUNET_assert(copystart < fm->msg + fm->message_size);
1447 fragheader.header.size = htons(copysize
1448 + sizeof(struct FragmentationHeader));
1449 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1454 // there is no need to split
1455 copystart = fm->msg;
1456 copysize = fm->message_size;
1460 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1461 + sizeof(struct GNUNET_MessageHeader);
1462 msgheader = GNUNET_malloc(size);
1463 msgheader->size = htons(size);
1464 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1466 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1467 getRadiotapHeader(plugin, session, radioHeader);
1469 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1470 getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
1472 //could be faster if content is just send and not copyed before
1473 //fragmentheader is needed
1474 //if (fm->message_size > WLAN_MTU)
1476 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1477 memcpy(&ieeewlanheader[1], &fragheader,
1478 sizeof(struct FragmentationHeader));
1479 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1480 memcpy(&fragheaderptr[1], copystart, copysize);
1484 memcpy(&ieeewlanheader[1], copystart, copysize);
1487 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1489 if (bytes == GNUNET_SYSERR)
1492 GNUNET_ERROR_TYPE_ERROR,
1493 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1494 errno, strerror(errno));
1497 GNUNET_assert(bytes != GNUNET_SYSERR);
1501 finish = GNUNET_malloc(sizeof( struct Finish_send));
1502 finish->plugin = plugin;
1503 finish->msgheader = (char *) msgheader + bytes;
1504 finish->size = size - bytes;
1505 finish->msgstart = msgheader;
1507 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1509 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1510 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1511 &finish_sending, finish);
1516 GNUNET_assert(bytes == size);
1518 GNUNET_free(msgheader);
1519 check_next_fragment_timeout(plugin);
1522 //check if this was the last fragment of this message, if true then queue at the end of the list
1523 if (copysize + copyoffset >= fm->message_size)
1525 GNUNET_assert(copysize + copyoffset == fm->message_size);
1527 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1528 plugin->pending_Fragment_Messages_tail, fm);
1530 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1531 plugin->pending_Fragment_Messages_tail, fm);
1532 // if fragments have opimized timeouts
1533 //sort_fragment_into_queue(plugin,fm);
1540 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1541 "do_transmit did nothing, should not happen!\n");
1545 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1547 struct Finish_send * finish;
1548 struct Plugin * plugin;
1552 plugin = finish->plugin;
1554 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1556 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1557 finish->msgheader, finish->size);
1558 GNUNET_assert(bytes != GNUNET_SYSERR);
1560 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1561 if (bytes != finish->size)
1564 finish->msgheader = finish->msgheader + bytes;
1565 finish->size = finish->size - bytes;
1566 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1567 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1568 &finish_sending, finish);
1572 GNUNET_free(finish->msgstart);
1573 GNUNET_free(finish);
1574 check_next_fragment_timeout(plugin);
1580 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1581 struct Radiotap_Send * header)
1584 if (session != NULL)
1586 header->rate = session->rate;
1587 header->tx_power = session->tx_power;
1588 header->antenna = session->antenna;
1593 header->tx_power = 0;
1594 header->antenna = 0;
1602 * function to generate the wlan hardware header for one packet
1603 * @param Header address to write the header to
1604 * @param to_mac_addr address of the recipient
1605 * @param plugin pointer to the plugin struct
1606 * @return GNUNET_YES if there was no error
1610 getWlanHeader(struct ieee80211_frame * Header, const char * const to_mac_addr,
1611 struct Plugin * plugin)
1613 Header->i_fc[0] = 0x80;
1614 Header->i_fc[1] = 0x00;
1615 memcpy(&Header->i_addr3, mac_bssid, sizeof(mac_bssid));
1616 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1617 memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1624 * @param msgbuf pointer tor the data
1625 * @param msgbuf_size size of the data
1627 * @return 32bit crc value
1631 getcrc32(const char *msgbuf, size_t msgbuf_size)
1633 //TODO calc some crc
1640 * @param msgbuf pointer tor the data
1641 * @param msgbuf_size size of the data
1643 * @return 16bit crc value
1647 getcrc16(const char *msgbuf, size_t msgbuf_size)
1649 //TODO calc some crc
1654 * Function that can be used by the transport service to transmit
1655 * a message using the plugin.
1657 * @param cls closure
1658 * @param target who should receive this message
1659 * @param priority how important is the message
1660 * @param msgbuf the message to transmit
1661 * @param msgbuf_size number of bytes in 'msgbuf'
1662 * @param timeout when should we time out
1663 * @param session which session must be used (or NULL for "any")
1664 * @param addr the address to use (can be NULL if the plugin
1665 * is "on its own" (i.e. re-use existing TCP connection))
1666 * @param addrlen length of the address in bytes
1667 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1668 * otherwise the plugin may use other addresses or
1669 * existing connections (if available)
1670 * @param cont continuation to call once the message has
1671 * been transmitted (or if the transport is ready
1672 * for the next transmission call; or if the
1673 * peer disconnected...)
1674 * @param cont_cls closure for cont
1675 * @return number of bytes used (on the physical network, with overheads);
1676 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1677 * and does NOT mean that the message was not transmitted (DV)
1680 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1681 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1682 struct GNUNET_TIME_Relative timeout, struct Session *session,
1683 const void *addr, size_t addrlen, int force_address,
1684 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1686 struct Plugin * plugin = cls;
1687 struct PendingMessage * newmsg = NULL;
1688 struct WlanHeader * wlanheader = NULL;
1690 //check if msglen > 0
1691 GNUNET_assert(msgbuf_size > 0);
1693 //get session if needed
1694 if (session == NULL)
1696 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1698 session = get_Session(plugin, addr);
1702 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1703 _("Wlan Address len %d is wrong\n"), addrlen);
1708 //TODO target "problem" not solved
1709 //if (session->target != NULL){
1710 // GNUNET_assert(session->target == *target);
1712 session->target = *target;
1718 //queue message in session
1719 //test if there is no other message in the "queue"
1720 //FIXME: to many send requests
1721 //GNUNET_assert (session->pending_message == NULL);
1722 if (session->pending_message != NULL)
1724 newmsg = session->pending_message;
1726 GNUNET_ERROR_TYPE_ERROR,
1727 "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",
1728 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1729 session->fragment_messages_out_count);
1730 if (session->pending_message2 != NULL)
1733 GNUNET_ERROR_TYPE_ERROR,
1734 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1739 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1740 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1741 wlanheader = (struct WlanHeader *) newmsg->msg;
1742 //copy msg to buffer, not fragmented / segmented yet, but with message header
1743 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1744 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1745 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1746 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1747 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1748 newmsg->transmit_cont = cont;
1749 newmsg->transmit_cont_cls = cont_cls;
1750 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1752 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1754 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1756 if (session->pending_message == NULL)
1758 session->pending_message = newmsg;
1762 session->pending_message2 = newmsg;
1766 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1767 "New message for %p with size (incl wlan header) %u added\n", session,
1768 newmsg->message_size);
1772 queue_Session(plugin, session);
1774 check_fragment_queue(plugin);
1775 //FIXME not the correct size
1781 * function to get the first message in the fragement queue (out) of a session
1782 * @param session pointer to the session
1783 * @return pointer to the struct FragmentMessage
1785 static struct FragmentMessage *
1786 get_fragment_message_from_session(struct Session * session)
1788 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1791 if (fm->session == session)
1801 * function to get the message in the fragement queue (out) of a session with a specific id
1802 * @param session pointer to the session
1803 * @param message_id id of the message
1804 * @return pointer to the struct FragmentMessage
1806 static struct FragmentMessage *
1807 get_fragment_message_from_session_and_id(struct Session * session,
1808 uint32_t message_id)
1810 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1813 if ((fm->session == session) && (fm->message_id_out == message_id))
1823 * Function that can be used to force the plugin to disconnect
1824 * from the given peer and cancel all previous transmissions
1825 * (and their continuation).
1827 * @param cls closure
1828 * @param target peer from which to disconnect
1831 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1833 struct Plugin *plugin = cls;
1834 struct Sessionqueue * queue = plugin->sessions;
1835 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1836 struct PendingMessage * pm = NULL;
1837 struct FragmentMessage * fm;
1838 struct Receive_Message_Queue * receive_queue;
1840 // just look at all the session for the needed one
1841 while (queue != NULL)
1843 // content is never NULL
1844 GNUNET_assert (queue->content != NULL);
1845 if (memcmp(target, &(queue->content->target),
1846 sizeof(struct GNUNET_PeerIdentity)) == 0)
1849 //is this session pending for send
1850 while (pendingsession != NULL)
1852 if (pendingsession->content == queue->content)
1854 plugin->pendingsessions--;
1855 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1856 plugin->pending_Sessions_tail, pendingsession);
1857 GNUNET_free(pendingsession);
1860 pendingsession = pendingsession->next;
1863 //is something of this session in the fragment queue?
1864 fm = get_fragment_message_from_session(queue->content);
1867 free_fragment_message(plugin, fm);
1868 fm = get_fragment_message_from_session(queue->content);
1870 check_next_fragment_timeout(plugin);
1872 //dispose all received fragments
1873 receive_queue = get_receive_message_from_session(plugin,
1875 while (receive_queue != NULL)
1877 free_receive_message(plugin, receive_queue);
1878 receive_queue = get_receive_message_from_session(plugin,
1882 // remove PendingMessage
1883 pm = queue->content->pending_message;
1886 GNUNET_free_non_null(pm->msg);
1890 GNUNET_free(queue->content);
1891 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1893 plugin->session_count--;
1898 queue = queue->next;
1903 * Convert the transports address to a nice, human-readable
1906 * @param cls closure
1907 * @param type name of the transport that generated the address
1908 * @param addr one of the addresses of the host, NULL for the last address
1909 * the specific address format depends on the transport
1910 * @param addrlen length of the address
1911 * @param numeric should (IP) addresses be displayed in numeric form?
1912 * @param timeout after how long should we give up?
1913 * @param asc function to call on each string
1914 * @param asc_cls closure for asc
1917 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1918 const void *addr, size_t addrlen, int numeric,
1919 struct GNUNET_TIME_Relative timeout,
1920 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1923 const unsigned char * input;
1925 //GNUNET_assert(cls !=NULL);
1928 /* invalid address (MAC addresses have 6 bytes) */
1933 input = (const unsigned char*) addr;
1934 GNUNET_snprintf(ret, sizeof(ret),
1935 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1936 input[0], input[1], input[2], input[3], input[4], input[5]);
1941 * Another peer has suggested an address for this
1942 * peer and transport plugin. Check that this could be a valid
1943 * address. If so, consider adding it to the list
1946 * @param cls closure
1947 * @param addr pointer to the address
1948 * @param addrlen length of addr
1949 * @return GNUNET_OK if this is a plausible address for this peer
1954 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1956 //struct Plugin *plugin = cls;
1958 /* check if the address is plausible; if so,
1959 add it to our list! */
1961 GNUNET_assert(cls !=NULL);
1962 //FIXME mitm is not checked
1963 //Mac Address has 6 bytes
1966 /* TODO check for bad addresses like multicast, broadcast, etc */
1970 return GNUNET_SYSERR;
1974 * Function called for a quick conversion of the binary address to
1975 * a numeric address. Note that the caller must not free the
1976 * address and that the next call to this function is allowed
1977 * to override the address again.
1979 * @param cls closure
1980 * @param addr binary address
1981 * @param addrlen length of the address
1982 * @return string representing the same address
1985 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
1987 static char ret[40];
1988 const struct MacAddress *mac;
1990 if (addrlen != sizeof(struct MacAddress))
1996 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
1997 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
1998 mac->mac[4], mac->mac[5]);
2003 * function to check if bitfield is representation of fragments of the message
2004 * @param rec_message message to check
2008 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
2010 uint64_t checkfragments = 0;
2011 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2013 while (rec_queue != NULL)
2015 setBit((char*) &checkfragments, rec_queue->num);
2016 rec_queue = rec_queue->next;
2019 GNUNET_assert(checkfragments == rec_message->received_fragments);
2023 * Function to test if fragment number already exists in the fragments received
2025 * @param rec_message message this fragment belongs to
2026 * @param fh Fragmentheader of the fragment
2027 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2031 is_double_msg(struct Receive_Message_Queue * rec_message,
2032 struct FragmentationHeader * fh)
2034 //test if bitfield is okay
2036 check_message_fragment_bitfield(rec_message);
2039 return testBit((char *) &rec_message->received_fragments, ntohs(
2040 fh->fragment_off_or_num));
2045 * Function to insert a fragment in a queue of a message
2046 * @param session session the fragment belongs to
2047 * @param rec_queue fragment to add
2051 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2052 struct Receive_Fragment_Queue * rx_frag)
2054 GNUNET_assert(rx_message != NULL);
2055 GNUNET_assert(rx_frag != NULL);
2057 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2058 struct WlanHeader * wlanheader = NULL;
2061 //this is the first fragment of the message (fragment id 0)
2062 if (rx_frag->num == 0)
2064 wlanheader = (struct WlanHeader *) rx_frag->msg;
2065 rx_message->rec_size = ntohs(wlanheader->header.size);
2069 while (rx_frag2 != NULL)
2071 if (rx_frag2->num > rx_frag->num)
2073 //next element number is grater than the current num
2074 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2075 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2078 rx_frag2 = rx_frag2->next;
2081 //no element has a grater number
2082 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2084 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2088 * Function to dispose the fragments received for a message and the message
2089 * @param plugin pointer to the plugin struct
2090 * @param rec_message pointer to the struct holding the message which should be freed
2094 free_receive_message(struct Plugin* plugin,
2095 struct Receive_Message_Queue * rx_message)
2097 GNUNET_assert(rx_message !=NULL);
2098 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
2099 struct Receive_Fragment_Queue * rec_queue2;
2101 while (rec_queue != NULL)
2103 rec_queue2 = rec_queue;
2104 rec_queue = rec_queue->next;
2105 GNUNET_free(rec_queue2);
2108 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
2110 GNUNET_assert(plugin->pending_receive_messages > 0);
2111 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
2113 plugin->pending_receive_messages--;
2114 rx_message->session->fragment_messages_in_count--;
2115 GNUNET_free(rx_message);
2119 * Function to check if all fragments of a message have been received
2120 * @param plugin the plugin handle
2121 * @param session_light information of the message sender
2122 * @param session session the message belongs to
2123 * @param rec_message pointer to the message that should be checked
2127 check_rec_finished_msg(struct Plugin* plugin,
2128 struct Session_light * session_light, struct Session * session,
2129 struct Receive_Message_Queue * rx_message)
2131 GNUNET_assert(rx_message !=NULL);
2133 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2134 int packetsize = rx_message->rec_size;
2137 uint64_t bitfield = 0;
2140 //check if first fragment is present
2141 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2145 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2146 else if (packetsize < sizeof(struct WlanHeader)
2147 + sizeof(struct GNUNET_MessageHeader))
2150 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2152 free_receive_message(plugin, rx_message);
2157 check_message_fragment_bitfield(rx_message);
2160 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2162 bitfield = ~bitfield;
2163 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2164 if (rx_message->received_fragments == bitfield)
2167 while (rx_frag != NULL)
2169 sum += rx_frag->size;
2170 rx_frag = rx_frag->next;
2172 //sum should always be smaller or equal of
2173 GNUNET_assert(sum <= packetsize);
2174 if (sum == packetsize)
2178 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2179 "check_rec_finished_msg: A message for %p is complete\n", session);
2183 //copy fragments together
2184 msg = GNUNET_malloc(packetsize);
2185 rx_frag = rx_message->frag_head;
2187 while (rx_frag != NULL)
2189 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2190 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2191 aktnum += rx_frag->size;
2192 rx_frag = rx_frag->next;
2195 free_receive_message(plugin, rx_message);
2196 //call wlan_process_helper to process the message
2197 wlan_data_massage_handler(plugin, session_light,
2198 (struct GNUNET_MessageHeader*) msg);
2199 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2208 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2211 GNUNET_assert(client != NULL);
2212 GNUNET_assert(cls != NULL);
2213 struct Session * session = (struct Session *) client;
2214 struct Plugin * plugin = (struct Plugin *) cls;
2216 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2217 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2218 distance[0].value = htonl(1);
2219 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2220 distance[1].value = htonl(0);
2223 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2224 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2225 wlan_plugin_address_to_string(NULL, session->addr, 6), htons(hdr->size));
2228 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2229 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2230 session->addr, sizeof(session->addr));
2234 * handels the data after all fragments are put together
2236 * @param session_light
2237 * @param hdr pointer to the data
2240 wlan_data_massage_handler(struct Plugin * plugin,
2241 struct Session_light * session_light,
2242 const struct GNUNET_MessageHeader * hdr)
2244 struct WlanHeader * wlanheader = NULL;
2245 struct Session * session = NULL;
2246 const char * tempmsg = NULL;
2247 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2248 struct GNUNET_PeerIdentity tmptarget;
2250 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2255 GNUNET_ERROR_TYPE_DEBUG,
2256 "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2260 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2261 + sizeof(struct GNUNET_MessageHeader))
2263 //packet not big enought
2267 GNUNET_assert(session_light != NULL);
2268 if (session_light->session == NULL)
2270 session_light->session = search_session(plugin, session_light->addr);
2272 session = session_light->session;
2273 wlanheader = (struct WlanHeader *) hdr;
2275 tempmsg = (char*) &wlanheader[1];
2276 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2278 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2281 //wrong crc, dispose message
2282 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2283 "Wlan message Header crc was wrong\n");
2287 //if not in session list
2288 if (session == NULL)
2292 GNUNET_ERROR_TYPE_DEBUG,
2293 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2294 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2295 sizeof(struct WlanHeader));
2297 //try if it is a hello message
2298 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2299 + sizeof(struct WlanHeader))
2301 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2303 if (GNUNET_HELLO_get_id(
2304 (const struct GNUNET_HELLO_Message *) temp_hdr,
2305 &tmptarget) == GNUNET_OK)
2307 session = create_session(plugin, session_light->addr);
2308 session_light->session = session;
2309 memcpy(&session->target, &tmptarget,
2310 sizeof(struct GNUNET_PeerIdentity));
2314 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2315 "WLAN client not in session list and hello message not okay\n");
2322 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2323 "WLAN client not in session list and not a hello message\n");
2330 GNUNET_ERROR_TYPE_WARNING,
2331 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2332 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2333 sizeof(struct WlanHeader));
2338 //"receive" the message
2341 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2342 (const char *) temp_hdr,
2343 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2349 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2350 "wlan_data_massage_handler got wrong message type\n");
2356 * function to add an ack to send it for a received fragment
2357 * @param plugin pointer to the global plugin structure
2358 * @param session pointer to the session this ack belongs to
2359 * @param bitfield bitfield to send
2360 * @param fh pointer to the fragmentation header which we would like to acknolage
2364 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2365 uint64_t bitfield, struct FragmentationHeader * fh)
2367 struct AckSendQueue * ack;
2369 GNUNET_assert(plugin != NULL);
2370 GNUNET_assert(session != NULL);
2371 GNUNET_assert(fh != NULL);
2373 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2374 ack->fragments_field = bitfield;
2375 ack->message_id = ntohl(fh->message_id);
2376 ack->session = session;
2378 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2379 plugin->ack_send_queue_tail, ack);
2384 * function to get the receive message from the message id and the session
2385 * @param plugin pointer to the plugin struct
2386 * @param session session this fragment belongs to
2387 * @param message_id id of the message
2390 struct Receive_Message_Queue *
2391 get_receive_message(struct Plugin * plugin, struct Session * session,
2392 uint32_t message_id)
2394 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2395 while (rec_message != NULL)
2397 if ((rec_message->message_id_in == message_id) && (rec_message->session
2402 rec_message = rec_message->next;
2408 * function to get the receive message of a session
2409 * @param plugin pointer to the plugin struct
2410 * @param session session this fragment belongs to
2413 struct Receive_Message_Queue *
2414 get_receive_message_from_session(struct Plugin * plugin,
2415 struct Session * session)
2417 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2418 while (rec_message != NULL)
2420 if (rec_message->session == session)
2424 rec_message = rec_message->next;
2430 * function to insert a received fragment into the right fragment queue of the right message
2431 * @param plugin pointer to the plugin struct
2432 * @param session_light pointer to the session_light struct of this message
2433 * @param session session this fragment belongs to
2434 * @param fh pointer to the header of the fragment
2435 * @return new fragment bitfield for the message
2439 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2440 struct Session_light * session_light, struct Session * session,
2441 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2443 struct Receive_Fragment_Queue * rx_frag = NULL;
2444 struct Receive_Message_Queue * rx_message;
2445 const char * tempmsg = (char*) &fh[1];
2446 uint64_t retval = 0;
2448 //TODO fragments do not timeout
2449 //check if message_id is right or it is a new msg
2450 GNUNET_assert(fh != NULL);
2452 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2454 if (rx_message == NULL)
2456 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2459 //new message incoming
2460 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2461 rx_message->message_id_in = ntohl(fh->message_id);
2462 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2463 rx_message->session = session;
2464 rx_message->timeout = GNUNET_TIME_absolute_add(
2465 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2466 rx_message->received_fragments = 0;
2468 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2470 session->fragment_messages_in_count++;
2471 plugin->pending_receive_messages++;
2475 GNUNET_ERROR_TYPE_DEBUG,
2476 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2477 rx_message->message_id_in, session->fragment_messages_in_count,
2478 plugin->pending_receive_messages);
2485 GNUNET_ERROR_TYPE_INFO,
2486 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2487 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2492 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2497 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2498 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2499 rx_frag->size = ntohs(fh->header.size)
2500 - sizeof(struct FragmentationHeader);
2501 rx_frag->num = ntohs(fh->fragment_off_or_num);
2502 rx_frag->msg = (char*) &(rx_frag[1]);
2503 //copy msg to buffer
2504 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2505 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2506 insert_fragment_in_queue(rx_message, rx_frag);
2508 retval = rx_message->received_fragments;
2512 GNUNET_ERROR_TYPE_DEBUG,
2513 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2514 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2515 rx_message->received_fragments, session);
2518 check_rec_finished_msg(plugin, session_light, session, rx_message);
2522 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2523 retval = rx_message->received_fragments;
2531 * Function used for to process the data received from the wlan interface
2533 * @param cls the plugin handle
2534 * @param session_light FIXME: document
2535 * @param hdr hdr of the GNUNET_MessageHeader
2538 wlan_data_helper(void *cls, struct Session_light * session_light,
2539 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2541 struct Plugin *plugin = cls;
2542 struct Session * session = NULL;
2544 struct FragmentationHeader * fh = NULL;
2545 struct FragmentationAckHeader * fah = NULL;
2546 struct FragmentMessage * fm = NULL;
2548 const char * tempmsg = NULL;
2550 uint64_t fragment_bitfield = 0;
2553 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2556 //TODO better DOS protection, error handling
2557 //TODO test first than create session
2558 GNUNET_assert(session_light != NULL);
2562 GNUNET_ERROR_TYPE_DEBUG,
2563 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2564 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2565 session_light->addr, 6));
2568 if (session_light->session == NULL)
2570 session_light->session = get_Session(plugin, session_light->addr);
2572 GNUNET_assert(GNUNET_HELLO_get_id(
2573 (const struct GNUNET_HELLO_Message *) &hdr[1],
2574 &(session_light->session->target) ) != GNUNET_SYSERR);
2579 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2582 GNUNET_assert(session_light != NULL);
2583 if (session_light->session == NULL)
2585 session_light->session = search_session(plugin, session_light->addr);
2587 session = session_light->session;
2589 fh = (struct FragmentationHeader *) hdr;
2590 tempmsg = (char*) &fh[1];
2594 GNUNET_ERROR_TYPE_DEBUG,
2595 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2596 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2597 hdr->size), wlan_plugin_address_to_string(NULL,
2598 session_light->addr, 6));
2601 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2603 //wrong crc, dispose message
2604 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2608 //if in the session list
2609 if (session != NULL)
2611 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2612 session_light, session, fh, rxinfo);
2618 GNUNET_ERROR_TYPE_INFO,
2619 "WLAN client not in session list, fragment num %u, message id %u\n",
2620 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2621 wlan_data_massage_handler(plugin, session_light,
2622 (struct GNUNET_MessageHeader *) tempmsg);
2623 session = session_light->session;
2624 //test if a session was created
2625 if (session == NULL)
2629 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2632 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2633 check_next_fragment_timeout(plugin);
2638 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2643 GNUNET_ERROR_TYPE_DEBUG,
2644 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2645 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2646 session_light->addr, 6));
2649 GNUNET_assert(session_light != NULL);
2650 if (session_light->session == NULL)
2652 session_light->session = search_session(plugin, session_light->addr);
2653 GNUNET_assert(session_light->session != NULL);
2655 session = session_light->session;
2656 fah = (struct FragmentationAckHeader *) hdr;
2657 fm = get_fragment_message_from_session_and_id(session, ntohl(
2662 fm->ack_bitfield = fm->ack_bitfield | ntohll(fah->fragment_field);
2663 check_finished_fragment(plugin, fm);
2667 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2668 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2678 GNUNET_ERROR_TYPE_INFO,
2679 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2680 ntohs(hdr->type), ntohs(hdr->size));
2686 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2687 "Helper finished\n");
2693 macprinter(const u_int8_t * mac)
2695 static char macstr[20];
2697 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2698 mac[2], mac[3], mac[4], mac[5]);
2703 * Function used for to process the data from the suid process
2705 * @param cls the plugin handle
2706 * @param client client that send the data (not used)
2707 * @param hdr header of the GNUNET_MessageHeader
2710 wlan_process_helper(void *cls, void *client,
2711 const struct GNUNET_MessageHeader *hdr)
2713 struct Plugin *plugin = cls;
2714 struct ieee80211_frame * wlanIeeeHeader = NULL;
2715 struct Session_light * session_light = NULL;
2716 struct Radiotap_rx * rxinfo;
2717 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2722 switch (ntohs(hdr->type))
2724 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2727 GNUNET_ERROR_TYPE_DEBUG,
2728 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2732 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2733 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2734 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2737 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2738 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2739 hdr->size), sizeof(struct ieee80211_frame)
2740 + sizeof(struct GNUNET_MessageHeader));
2743 /* FIXME: restart SUID process */
2746 rxinfo = (struct Radiotap_rx *) &hdr[1];
2747 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2749 //process only if it is an broadcast or for this computer both with the gnunet bssid
2752 if (memcmp(&(wlanIeeeHeader->i_addr3), mac_bssid, sizeof(struct MacAddress))
2755 //check for broadcast or mac
2756 if (memcmp(&(wlanIeeeHeader->i_addr1), bc_all_mac,
2757 sizeof(struct MacAddress) == 0) || memcmp(
2758 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2759 sizeof(struct MacAddress)) == 0)
2762 // process the inner data
2765 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2766 - sizeof(struct GNUNET_MessageHeader)
2767 - sizeof(struct Radiotap_rx);
2769 session_light = GNUNET_malloc(sizeof(struct Session_light));
2770 memcpy(session_light->addr, &(wlanIeeeHeader->i_addr2),
2771 sizeof(struct MacAddress));
2772 //session_light->session = search_session(plugin,session_light->addr);
2775 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2776 while (pos < datasize)
2778 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2781 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2782 pos += ntohs(temp_hdr->size);
2787 GNUNET_free(session_light);
2792 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2793 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2794 wlanIeeeHeader->i_addr1));
2801 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2802 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2803 wlanIeeeHeader->i_addr2));
2807 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2808 //TODO more control messages
2809 //TODO use struct wlan_helper_control
2810 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2813 /* FIXME: restart SUID process */
2816 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2818 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2819 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2820 wlan_plugin_address_to_string(cls, &plugin->mac_address,
2821 sizeof(struct MacAddress)));
2823 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2824 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2833 * We have been notified that wlan-helper has written something to stdout.
2834 * Handle the output, then reschedule this function to be called again once
2835 * more is available.
2837 * @param cls the plugin handle
2838 * @param tc the scheduling context
2841 wlan_plugin_helper_read(void *cls,
2842 const struct GNUNET_SCHEDULER_TaskContext *tc)
2844 struct Plugin *plugin = cls;
2845 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2850 "Start reading from STDIN\n");
2853 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2856 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2859 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2864 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2865 _("Finished reading from wlan-helper stdout with code: %d\n"),
2870 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2871 GNUNET_NO, GNUNET_NO);
2873 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2874 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2875 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2876 &wlan_plugin_helper_read, plugin);
2880 * Start the gnunet-wlan-helper process.
2882 * @param plugin the transport plugin
2883 * @param testmode should we use the dummy driver for testing?
2884 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2887 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2889 const char * filename = "gnunet-transport-wlan-helper";
2890 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2891 if (plugin->server_stdout == NULL)
2892 return GNUNET_SYSERR;
2894 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2895 if (plugin->server_stdin == NULL)
2896 return GNUNET_SYSERR;
2899 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2900 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2901 plugin->interface, testmode);
2903 /* Start the server process */
2905 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2906 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2907 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2908 if (plugin->server_proc == NULL)
2911 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2912 "Failed to start gnunet-wlan-helper process\n");
2914 return GNUNET_SYSERR;
2917 /* Close the write end of the read pipe */
2918 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2920 /* Close the read end of the write pipe */
2921 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2923 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2924 GNUNET_DISK_PIPE_END_READ);
2925 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2926 GNUNET_DISK_PIPE_END_WRITE);
2928 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2931 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2932 "Adding server_read_task for the wlan-helper\n");
2937 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2938 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2939 &wlan_plugin_helper_read, plugin);
2945 * Exit point from the plugin.
2946 * @param cls pointer to the api struct
2951 libgnunet_plugin_transport_wlan_done(void *cls)
2953 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2954 struct Plugin *plugin = api->cls;
2957 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2958 "libgnunet_plugin_transport_wlan_done started\n");
2961 GNUNET_assert(cls !=NULL);
2963 if (plugin->suid_tokenizer != NULL)
2964 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2966 if (plugin->data_tokenizer != NULL)
2967 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
2969 GNUNET_free_non_null(plugin->interface);
2970 GNUNET_free (plugin);
2976 * Entry point for the plugin.
2978 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2979 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2982 libgnunet_plugin_transport_wlan_init(void *cls)
2984 //struct GNUNET_SERVICE_Context *service;
2985 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2986 struct GNUNET_TRANSPORT_PluginFunctions *api;
2987 struct Plugin *plugin;
2988 static unsigned long long testmode = 0;
2990 GNUNET_assert(cls !=NULL);
2992 plugin = GNUNET_malloc (sizeof (struct Plugin));
2994 plugin->pendingsessions = 0;
2995 plugin->session_count = 0;
2996 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2997 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2998 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3000 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3003 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3005 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3006 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3008 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3010 api->send = &wlan_plugin_send;
3011 api->disconnect = &wlan_plugin_disconnect;
3012 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3013 api->check_address = &wlan_plugin_address_suggested;
3014 api->address_to_string = &wlan_plugin_address_to_string;
3018 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3020 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3021 "transport-wlan", "TESTMODE", &testmode))
3022 testmode = 0; //default value
3025 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3027 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3028 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3030 libgnunet_plugin_transport_wlan_done(api);
3036 set_next_beacon_time(plugin);
3038 wlan_transport_start_wlan_helper(plugin, testmode);
3040 start_next_message_id();
3043 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3049 /* end of plugin_transport_wlan.c */