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"
39 #define PROTOCOL_PREFIX "wlan"
42 * Max size of packet from helper
47 * Time until retransmission of a fragment in ms
49 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
51 #define FRAGMENT_QUEUE_SIZE 10
52 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
54 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
56 #define MESSAGES_IN_QUEUE_SIZE 10
57 #define MESSAGES_IN_QUEUE_PER_SESSION 1
59 #define HALLO_BEACON_SCALING_FACTOR 900
61 #define DEBUG_wlan GNUNET_YES
63 #define MESSAGE_LENGHT_UNKNOWN -1
64 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
67 * After how long do we expire an address that we
68 * learned from another peer if it is not reconfirmed
71 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
74 * Initial handshake message for a session.
79 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
81 struct GNUNET_MessageHeader header;
84 * Identit*mac_y of the node connecting (TCP client)
86 struct GNUNET_PeerIdentity clientIdentity;
91 * Encapsulation of all of the state of the plugin.
98 struct GNUNET_TRANSPORT_PluginEnvironment *env;
101 * List of open sessions. head
103 struct Sessionqueue *sessions;
106 * List of open sessions. tail
108 struct Sessionqueue *sessions_tail;
117 * encapsulation of data from the local wlan helper program
120 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
123 * encapsulation of packets received
126 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
129 * stdout pipe handle for the gnunet-wlan-helper process
131 struct GNUNET_DISK_PipeHandle *server_stdout;
134 * stdout file handle for the gnunet-wlan-helper process
136 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
139 * stdin pipe handle for the gnunet-wlan-helper process
141 struct GNUNET_DISK_PipeHandle *server_stdin;
144 * stdin file handle for the gnunet-wlan-helper process
146 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
149 * ID of the gnunet-wlan-server std read task
151 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
154 * ID of the gnunet-wlan-server std read task
156 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
159 * ID of the delay task for writing
161 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
164 * The process id of the wlan process
166 struct GNUNET_OS_Process *server_proc;
169 * The interface of the wlan card given to us by the user.
174 * The mac_address of the wlan card given to us by the helper.
176 struct MacAddress mac_address;
179 * Sessions currently pending for transmission
180 * to this peer, if any.
182 struct Sessionqueue * pending_Sessions;
185 * Sessions currently pending for transmission
186 * to this peer (tail), if any.
188 struct Sessionqueue * pending_Sessions_tail;
191 * number of pending sessions
193 unsigned int pendingsessions;
196 * Messages in the fragmentation queue, head
199 struct FragmentMessage * pending_Fragment_Messages_head;
202 * Messages in the fragmentation queue, tail
205 struct FragmentMessage * pending_Fragment_Messages_tail;
208 * number of pending fragment message
211 unsigned int pending_fragment_messages;
214 * Messages in the in Queue, head
217 struct Receive_Message_Queue * receive_messages_head;
220 * Messages in the in Queue, tail
223 struct Receive_Message_Queue * receive_messages_teil;
226 * number of messages in the in queue
229 unsigned int pending_receive_messages;
232 * time of the next "hello-beacon"
235 struct GNUNET_TIME_Absolute beacon_time;
238 * queue to send acks for received fragments (head)
241 struct AckSendQueue * ack_send_queue_head;
244 * queue to send acks for received fragments (tail)
247 struct AckSendQueue * ack_send_queue_tail;
252 * Struct to store data if file write did not accept the whole packet
256 struct Plugin * plugin;
258 struct GNUNET_MessageHeader * msgstart;
263 * Queue of sessions, for the general session queue and the pending session queue
268 struct Sessionqueue * next;
269 struct Sessionqueue * prev;
270 struct Session * content;
274 * Queue for the fragments received
277 struct Receive_Fragment_Queue
279 struct Receive_Fragment_Queue * next;
280 struct Receive_Fragment_Queue * prev;
287 * Queue for the fragments received
290 struct Receive_Message_Queue
292 struct Receive_Message_Queue * next;
294 struct Receive_Message_Queue * prev;
297 * current number for message incoming, to distinguish between the messages
299 uint32_t message_id_in;
302 * size of the message received,
303 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
304 * 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 struct AckSendQueue * next;
383 struct AckSendQueue * prev;
385 struct Session * session;
387 * ID of message, to distinguish between the messages, picked randomly.
392 * Bit field for received fragments
394 uint64_t fragments_field;
399 * Session infos gathered from a messages
405 * the session this message belongs to
407 struct Session * session;
415 * Session handle for connections.
423 struct SessionHeader header;
426 * Pointer to the global plugin struct.
428 struct Plugin *plugin;
431 * Message currently pending for transmission
432 * to this peer, if any.
434 struct PendingMessage *pending_message;
437 * Message currently pending for transmission
438 * to this peer, if any.
440 struct PendingMessage *pending_message2;
443 * To whom are we talking to (set to our identity
444 * if we are still waiting for the welcome message)
446 struct GNUNET_PeerIdentity target;
454 * Address of the other peer (either based on our 'connect'
455 * call or on our 'accept' call).
460 * Last activity on this connection. Used to select preferred
463 struct GNUNET_TIME_Absolute last_activity;
466 * count of messages in the fragment out queue for this session
469 int fragment_messages_out_count;
472 * count of messages in the fragment in queue for this session
475 int fragment_messages_in_count;
485 * Struct for Messages in the fragment queue
488 struct FragmentMessage
491 * Session this message belongs to
494 struct Session *session;
497 * This is a doubly-linked list.
499 struct FragmentMessage *next;
502 * This is a doubly-linked list.
504 struct FragmentMessage *prev;
507 * The pending message
512 * Timeout value for the pending message.
514 struct GNUNET_TIME_Absolute timeout;
517 * Timeout value for the pending fragments.
518 * Stores the time when the next msg fragment ack has to be received
520 struct GNUNET_TIME_Absolute next_ack;
523 * bitfield with all acks received for this message
525 uint64_t ack_bitfield;
528 * Size of the message
533 * pos / next fragment number in the message, for fragmentation/segmentation,
534 * some acks can be missing but there is still time
536 uint32_t message_pos;
539 * current number for message outgoing, to distinguish between the messages
541 uint32_t message_id_out;
545 * Header for messages which need fragmentation
550 struct GNUNET_MessageHeader header;
553 * checksum/error correction
555 uint32_t crc GNUNET_PACKED;
558 * To whom are we talking to (set to our identity
559 * if we are still waiting for the welcome message)
561 struct GNUNET_PeerIdentity target;
563 // followed by payload
568 * Header for messages which need fragmentation
570 struct FragmentationHeader
573 struct GNUNET_MessageHeader header;
576 * ID of message, to distinguish between the messages, picked randomly.
578 uint32_t message_id GNUNET_PACKED;
581 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
583 uint16_t fragment_off_or_num GNUNET_PACKED;
586 * CRC of fragment (for error checking)
588 uint16_t message_crc GNUNET_PACKED;
590 // followed by payload
595 * Header for messages which need fragmentation
597 struct FragmentationAckHeader
600 struct GNUNET_MessageHeader header;
603 * ID of message, to distinguish between the messages, picked randomly.
605 uint32_t message_id GNUNET_PACKED;
608 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
610 uint64_t fragment_field GNUNET_PACKED;
615 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
616 struct Radiotap_Send * Header);
619 getWlanHeader(struct ieee80211_frame * Header, const char * to_mac_addr,
620 struct Plugin * plugin);
623 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
626 getcrc16(const char *msgbuf, size_t msgbuf_size);
629 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
632 check_fragment_queue(struct Plugin * plugin);
635 getcrc32(const char *msgbuf, size_t msgbuf_size);
638 free_receive_message(struct Plugin* plugin,
639 struct Receive_Message_Queue * rec_message);
641 struct Receive_Message_Queue *
642 get_receive_message_from_session(struct Plugin * plugin,
643 struct Session * session);
646 wlan_data_helper(void *cls, struct Session_light * session_light,
647 const struct GNUNET_MessageHeader * hdr);
650 wlan_process_helper(void *cls, void *client,
651 const struct GNUNET_MessageHeader *hdr);
654 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
657 wlan_data_massage_handler(struct Plugin * plugin,
658 struct Session_light * session_light,
659 const struct GNUNET_MessageHeader * hdr);
662 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen);
664 struct Receive_Message_Queue *
665 get_receive_message(struct Plugin * plugin, struct Session * session,
666 uint32_t message_id);
669 htonll(uint64_t input)
675 ntohll(uint64_t input)
681 * Sets a bit active in the bitArray. Increment bit-specific
682 * usage counter on disk only if below 4bit max (==15).
684 * @param bitArray memory area to set the bit in
685 * @param bitIdx which bit to set
688 setBit(char *bitArray, unsigned int bitIdx)
691 unsigned int targetBit;
693 arraySlot = bitIdx / 8;
694 targetBit = (1L << (bitIdx % 8));
695 bitArray[arraySlot] |= targetBit;
699 * Clears a bit from bitArray. Bit is cleared from the array
700 * only if the respective usage counter on the disk hits/is zero.
702 * @param bitArray memory area to set the bit in
703 * @param bitIdx which bit to unset
706 clearBit(char *bitArray, unsigned int bitIdx)
709 unsigned int targetBit;
712 targetBit = (1L << (bitIdx % 8));
713 bitArray[slot] = bitArray[slot] & (~targetBit);
717 * Checks if a bit is active in the bitArray
719 * @param bitArray memory area to set the bit in
720 * @param bitIdx which bit to test
721 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
724 testBit(char *bitArray, unsigned int bitIdx)
727 unsigned int targetBit;
730 targetBit = (1L << (bitIdx % 8));
731 if (bitArray[slot] & targetBit)
738 * get the next message number, at the moment just a random one
739 * @return returns the next valid message-number for sending packets
742 get_next_message_id()
744 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
748 * start next message number generator
749 * (not necessary at the moment)
752 start_next_message_id()
754 //GNUNET_CRYPTO_random_init;
758 * search for a session with the addr
760 * @param plugin pointer to the plugin struct
761 * @param addr pointer to the mac address of the peer
762 * @return returns the session
765 static struct Session *
766 search_session(struct Plugin *plugin, const uint8_t * addr)
768 struct Sessionqueue * queue = plugin->sessions;
769 struct Sessionqueue * lastitem = NULL;
771 //just look at all the session for the needed one
772 while (queue != NULL)
774 // content is never NULL
775 GNUNET_assert (queue->content != NULL);
776 char * addr2 = queue->content->addr;
777 if (memcmp(addr, addr2, 6) == 0)
780 return queue->content;
790 * create a new session
792 * @param plugin pointer to the plugin struct
793 * @param addr pointer to the mac address of the peer
794 * @return returns the session
797 static struct Session *
798 create_session(struct Plugin *plugin, const uint8_t * addr)
800 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
802 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
804 queue->content = GNUNET_malloc (sizeof (struct Session));
805 queue->content->plugin = plugin;
806 memcpy(queue->content->addr, addr, 6);
807 queue->content->fragment_messages_out_count = 0;
808 queue->content->fragment_messages_in_count = 0;
810 plugin->session_count++;
813 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
814 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
817 return queue->content;
821 * get Session from address, create if no session exists
823 * @param plugin pointer to the plugin struct
824 * @param addr pointer to the mac address of the peer
825 * @return returns the session
827 //TODO add other possibilities to find the right session (are there other?)
828 static struct Session *
829 get_Session(struct Plugin *plugin, const uint8_t * addr)
831 struct Session * session = search_session(plugin, addr);
837 return create_session(plugin, addr);
839 /* -- not needed, layer above already has it--
840 //queue welcome message for new sessions, not realy needed
841 //struct WelcomeMessage welcome;
842 struct PendingMessage *pm;
843 pm = GNUNET_malloc (sizeof (struct PendingMessage));
844 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
845 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
846 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
847 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
848 //welcome.clientIdentity = *plugin->env->my_identity;
849 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
850 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
851 queue->content->pending_message = pm;
852 plugin->pendingsessions ++;
853 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
855 check_fragment_queue(plugin);
860 * Queue the session to send data
864 queue_Session(struct Plugin *plugin, struct Session * session)
866 struct Sessionqueue * queue = plugin->pending_Sessions;
867 struct Sessionqueue * lastitem = NULL;
869 while (queue != NULL)
871 // content is never NULL
872 GNUNET_assert (queue->content != NULL);
873 // is session already in queue?
874 if (session == queue->content)
883 // Session is not in the queue
885 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
886 queue->content = session;
889 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
890 plugin->pending_Sessions_tail,
891 plugin->pending_Sessions_tail, queue);
892 plugin->pendingsessions++;
898 * Function to schedule the write task, executed after a delay
901 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
903 struct Plugin * plugin = cls;
904 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
906 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
909 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
910 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
912 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
913 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
914 &do_transmit, plugin);
920 * Function to calculate the time of the next periodic "hello-beacon"
923 set_next_beacon_time(struct Plugin * const plugin)
925 //under 10 known peers: once a second
926 if (plugin->session_count < 10)
928 plugin->beacon_time = GNUNET_TIME_absolute_add(
929 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
930 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
932 //under 30 known peers: every 10 seconds
933 else if (plugin->session_count < 30)
935 plugin->beacon_time = GNUNET_TIME_absolute_add(
936 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
937 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
939 //over 30 known peers: once a minute
942 plugin->beacon_time = GNUNET_TIME_absolute_add(
943 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
944 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
949 struct GNUNET_TIME_Relative
950 get_next_frag_timeout(struct FragmentMessage * fm)
952 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
953 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
958 * Function to get the timeout value for acks for this session
961 struct GNUNET_TIME_Relative
962 get_ack_timeout(struct FragmentMessage * fm)
964 return FRAGMENT_TIMEOUT;
968 * Function to set the timer for the next timeout of the fragment queue
969 * @param plugin the handle to the plugin struct
972 check_next_fragment_timeout(struct Plugin * const plugin)
974 struct FragmentMessage * fm;
975 struct GNUNET_TIME_Relative next_send;
978 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
980 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
981 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
983 fm = plugin->pending_Fragment_Messages_head;
985 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
987 //check if some acks are in the queue
988 if (plugin->ack_send_queue_head != NULL)
990 next_send = GNUNET_TIME_UNIT_ZERO;
992 //check if there are some fragments in the queue
995 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
999 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
1002 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1003 &delay_fragment_task, plugin);
1008 * Function to get the next queued Session, removes the session from the queue
1011 static struct Session *
1012 get_next_queue_Session(struct Plugin * plugin)
1014 struct Session * session;
1015 struct Sessionqueue * sessionqueue;
1016 struct Sessionqueue * sessionqueue_alt;
1017 struct PendingMessage * pm;
1018 sessionqueue = plugin->pending_Sessions;
1019 while (sessionqueue != NULL)
1021 session = sessionqueue->content;
1023 pm = session->pending_message;
1027 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1028 "pending message is empty, should not happen. session %p\n",
1032 GNUNET_assert(pm != NULL);
1034 //check for message timeout
1035 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1037 //check if session has no message in the fragment queue
1038 if (session->fragment_messages_out_count
1039 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1041 plugin->pendingsessions--;
1042 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1043 plugin->pending_Sessions_tail, sessionqueue);
1044 GNUNET_free(sessionqueue);
1050 sessionqueue = sessionqueue->next;
1056 session->pending_message = session->pending_message2;
1057 session->pending_message2 = NULL;
1059 //call the cont func that it did not work
1060 if (pm->transmit_cont != NULL)
1061 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1063 GNUNET_free(pm->msg);
1066 if (session->pending_message == NULL)
1068 sessionqueue_alt = sessionqueue;
1069 sessionqueue = sessionqueue->next;
1070 plugin->pendingsessions--;
1071 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1072 plugin->pending_Sessions_tail, sessionqueue_alt);
1074 GNUNET_free(sessionqueue_alt);
1084 * Function to sort the message into the message fragment queue
1085 * @param plugin the plugin struct
1086 * @param fm message to sort into the queue
1089 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
1091 struct FragmentMessage * fm2;
1092 //sort into the list at the right position
1094 fm2 = plugin->pending_Fragment_Messages_head;
1098 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
1101 GNUNET_CONTAINER_DLL_insert_before(plugin->pending_Fragment_Messages_head,
1102 plugin->pending_Fragment_Messages_tail,fm2,fm);
1111 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1112 plugin->pending_Fragment_Messages_tail,fm);
1116 * frees the space of a message in the fragment queue (send queue)
1117 * @param plugin the plugin struct
1118 * @param fm message to free
1121 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1125 (fm->session->fragment_messages_out_count)--;
1126 GNUNET_free_non_null(fm->msg);
1127 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1128 plugin->pending_Fragment_Messages_tail, fm);
1130 plugin->pending_fragment_messages--;
1133 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1134 "free pending fragment messages, pending messages remaining %u\n",
1135 plugin->pending_fragment_messages);
1141 * Function to check if there is some space in the fragment queue
1142 * inserts a message if space is available
1143 * @param plugin the plugin struct
1147 check_fragment_queue(struct Plugin * plugin)
1149 struct Session * session;
1150 struct FragmentMessage * fm;
1151 struct GNUNET_PeerIdentity pid;
1153 struct PendingMessage * pm;
1155 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
1157 session = get_next_queue_Session(plugin);
1158 if (session != NULL)
1160 pm = session->pending_message;
1161 session->pending_message = NULL;
1162 session->fragment_messages_out_count++;
1163 GNUNET_assert(pm != NULL);
1165 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1166 fm->message_size = pm->message_size;
1168 fm->session = session;
1169 fm->timeout.abs_value = pm->timeout.abs_value;
1170 fm->message_pos = 0;
1171 fm->next_ack = GNUNET_TIME_absolute_get();
1172 fm->message_id_out = get_next_message_id();
1173 fm->ack_bitfield = 0;
1175 sort_fragment_into_queue(plugin, fm);
1176 plugin->pending_fragment_messages++;
1178 if (pm->transmit_cont != NULL)
1180 pid = session->target;
1181 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1183 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1184 "called pm->transmit_cont for %p\n", session);
1190 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1191 "no pm->transmit_cont for %p\n", session);
1196 if (session->pending_message2 != NULL)
1198 session->pending_message = session->pending_message2;
1199 session->pending_message2 = NULL;
1201 queue_Session(plugin, session);
1204 //check if timeout changed
1205 check_next_fragment_timeout(plugin);
1211 * Funktion to check if all fragments where send and the acks received
1212 * frees the space if finished
1213 * @param plugin the plugin struct
1214 * @param fm the message to check
1217 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1219 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1220 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1221 - sizeof(struct FragmentationHeader)));
1222 uint64_t tmpfield = UINT64_MAX;
1223 tmpfield = tmpfield >> maxack;
1227 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1228 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1229 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1232 if (fm->ack_bitfield == tmpfield)
1235 free_fragment_message(plugin, fm);
1238 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1239 "Finished sending and got all acks for a fragmented message\n");
1242 check_next_fragment_timeout(plugin);
1243 check_fragment_queue(plugin);
1249 * Function to set the next fragment number
1250 * @param fm use this FragmentMessage
1254 set_next_message_fragment_pos(struct FragmentMessage * fm)
1257 //check if retransmit is needed
1258 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1261 // be positive and try again later :-D
1262 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1263 // find first missing fragment
1265 fm->message_pos = 0;
1268 //test if ack 0 (or X) was already received
1269 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1277 send_hello_beacon(struct Plugin * plugin)
1281 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1286 struct GNUNET_MessageHeader * msgheader = NULL;
1287 struct ieee80211_frame * ieeewlanheader = NULL;
1288 struct Radiotap_Send * radioHeader = NULL;
1289 struct GNUNET_MessageHeader * msgheader2 = NULL;
1291 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1292 *(plugin->env->our_hello)) <= WLAN_MTU);
1293 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1294 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1295 + GNUNET_HELLO_size(*(plugin->env->our_hello));
1297 msgheader = GNUNET_malloc(size);
1298 msgheader->size = htons(size);
1299 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1301 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1302 getRadiotapHeader(plugin, NULL, radioHeader);
1303 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1304 getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
1306 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1307 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1308 + sizeof(struct GNUNET_MessageHeader));
1310 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1311 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1312 *(plugin->env->our_hello)));
1314 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1316 if (bytes == GNUNET_SYSERR)
1318 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1319 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1320 errno, strerror(errno));
1323 GNUNET_assert(bytes != GNUNET_SYSERR);
1324 GNUNET_assert(bytes == size);
1325 GNUNET_free(msgheader);
1327 set_next_beacon_time(plugin);
1328 check_next_fragment_timeout(plugin);
1332 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1337 struct GNUNET_MessageHeader * msgheader = NULL;
1338 struct ieee80211_frame * ieeewlanheader = NULL;
1339 struct Radiotap_Send * radioHeader = NULL;
1340 struct FragmentationAckHeader * msgheader2 = NULL;
1342 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1345 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1346 "Sending ack for message_id %u with fragment field %u\n",
1347 ack->message_id, ack->fragments_field);
1350 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1351 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1352 msgheader = GNUNET_malloc(size);
1353 msgheader->size = htons(size);
1354 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1356 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1357 getRadiotapHeader(plugin, ack->session, radioHeader);
1358 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1359 getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
1361 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1362 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1363 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1364 msgheader2->message_id = htonl(ack->message_id);
1365 msgheader2->fragment_field = htonll(ack->fragments_field);
1367 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1368 if (bytes == GNUNET_SYSERR)
1370 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1371 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1372 errno, strerror(errno));
1375 GNUNET_assert(bytes != GNUNET_SYSERR);
1376 GNUNET_assert(bytes == size);
1377 GNUNET_free(msgheader);
1378 check_next_fragment_timeout(plugin);
1382 * Function called when wlan helper is ready to get some data
1384 * @param cls closure
1385 * @param tc GNUNET_SCHEDULER_TaskContext
1389 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1392 struct Plugin * plugin = cls;
1393 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1395 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1398 struct Session * session = NULL;
1399 struct FragmentMessage * fm = NULL;
1400 struct ieee80211_frame * ieeewlanheader = NULL;
1401 struct Radiotap_Send * radioHeader = NULL;
1402 struct GNUNET_MessageHeader * msgheader = NULL;
1404 struct FragmentationHeader fragheader;
1405 struct FragmentationHeader * fragheaderptr = NULL;
1406 struct Finish_send * finish = NULL;
1407 struct AckSendQueue * ack;
1410 const char * copystart = NULL;
1411 uint16_t copysize = 0;
1412 uint copyoffset = 0;
1414 if (plugin->ack_send_queue_head != NULL)
1416 ack = plugin->ack_send_queue_head;
1417 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1418 plugin->ack_send_queue_tail, ack);
1419 send_ack(plugin, ack);
1424 //test if a "hello-beacon" has to be send
1425 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1427 send_hello_beacon(plugin);
1433 fm = plugin->pending_Fragment_Messages_head;
1436 session = fm->session;
1437 GNUNET_assert(session != NULL);
1439 // test if message timed out
1440 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1443 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1446 check_fragment_queue(plugin);
1447 free_fragment_message(plugin, fm);
1453 //if (fm->message_size > WLAN_MTU)
1455 size += sizeof(struct FragmentationHeader);
1457 set_next_message_fragment_pos(fm);
1459 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1464 GNUNET_ERROR_TYPE_DEBUG,
1465 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1466 fm->message_id_out, fm->message_pos, copysize
1467 + sizeof(struct FragmentationHeader), copyoffset,
1468 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1471 fragheader.fragment_off_or_num = htons(fm->message_pos);
1472 fragheader.message_id = htonl(fm->message_id_out);
1473 copystart = fm->msg + copyoffset;
1474 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1475 WLAN_MTU - sizeof(struct FragmentationHeader));
1477 if (copyoffset >= fm->message_size)
1480 GNUNET_ERROR_TYPE_ERROR,
1481 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1482 copyoffset, fm->message_size, WLAN_MTU
1483 - sizeof(struct FragmentationHeader), copysize,
1486 GNUNET_assert(copyoffset < fm->message_size);
1487 //FIXME remove later
1488 GNUNET_assert(copystart < fm->msg + fm->message_size);
1490 fragheader.header.size = htons(copysize
1491 + sizeof(struct FragmentationHeader));
1492 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1497 // there is no need to split
1498 copystart = fm->msg;
1499 copysize = fm->message_size;
1503 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1504 + sizeof(struct GNUNET_MessageHeader);
1505 msgheader = GNUNET_malloc(size);
1506 msgheader->size = htons(size);
1507 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1509 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1510 getRadiotapHeader(plugin, session, radioHeader);
1512 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1513 getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
1515 //could be faster if content is just send and not copyed before
1516 //fragmentheader is needed
1517 //if (fm->message_size > WLAN_MTU)
1519 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1520 memcpy(&ieeewlanheader[1], &fragheader,
1521 sizeof(struct FragmentationHeader));
1522 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1523 memcpy(&fragheaderptr[1], copystart, copysize);
1527 memcpy(&ieeewlanheader[1], copystart, copysize);
1530 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1532 if (bytes == GNUNET_SYSERR)
1535 GNUNET_ERROR_TYPE_ERROR,
1536 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1537 errno, strerror(errno));
1540 GNUNET_assert(bytes != GNUNET_SYSERR);
1544 finish = GNUNET_malloc(sizeof( struct Finish_send));
1545 finish->plugin = plugin;
1546 finish->msgheader = (char *) msgheader + bytes;
1547 finish->size = size - bytes;
1548 finish->msgstart = msgheader;
1550 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1552 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1553 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1554 &finish_sending, finish);
1559 GNUNET_assert(bytes == size);
1561 GNUNET_free(msgheader);
1562 check_next_fragment_timeout(plugin);
1565 //check if this was the last fragment of this message, if true then queue at the end of the list
1566 if (copysize + copyoffset >= fm->message_size)
1568 GNUNET_assert(copysize + copyoffset == fm->message_size);
1570 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1571 plugin->pending_Fragment_Messages_tail, fm);
1573 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1574 plugin->pending_Fragment_Messages_tail, fm);
1575 // if fragments have opimized timeouts
1576 //sort_fragment_into_queue(plugin,fm);
1583 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1584 "do_transmit did nothing, should not happen!\n");
1588 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1590 struct Finish_send * finish;
1591 struct Plugin * plugin;
1595 plugin = finish->plugin;
1597 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1599 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1600 finish->msgheader, finish->size);
1601 GNUNET_assert(bytes != GNUNET_SYSERR);
1603 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1604 if (bytes != finish->size)
1607 finish->msgheader = finish->msgheader + bytes;
1608 finish->size = finish->size - bytes;
1609 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1610 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1611 &finish_sending, finish);
1615 GNUNET_free(finish->msgstart);
1616 GNUNET_free(finish);
1617 check_next_fragment_timeout(plugin);
1623 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1624 struct Radiotap_Send * header)
1627 if (session != null){
1628 header->rate = session->rate;
1629 header->tx_power = session->tx_power;
1630 header->antenna = session->antenna;
1633 header->tx_power = 0;
1634 header->antenna = 0;
1642 * function to generate the wlan hardware header for one packet
1643 * @param Header address to write the header to
1644 * @param to_mac_addr address of the recipient
1645 * @param plugin pointer to the plugin struct
1646 * @return GNUNET_YES if there was no error
1650 getWlanHeader(struct ieee80211_frame * Header, const char * const to_mac_addr,
1651 struct Plugin * plugin)
1653 memcpy(&Header->i_addr3, mac_bssid, sizeof(mac_bssid));
1654 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1655 memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1662 * @param msgbuf pointer tor the data
1663 * @param msgbuf_size size of the data
1665 * @return 32bit crc value
1669 getcrc32(const char *msgbuf, size_t msgbuf_size)
1671 //TODO calc some crc
1678 * @param msgbuf pointer tor the data
1679 * @param msgbuf_size size of the data
1681 * @return 16bit crc value
1685 getcrc16(const char *msgbuf, size_t msgbuf_size)
1687 //TODO calc some crc
1692 * Function that can be used by the transport service to transmit
1693 * a message using the plugin.
1695 * @param cls closure
1696 * @param target who should receive this message
1697 * @param priority how important is the message
1698 * @param msgbuf the message to transmit
1699 * @param msgbuf_size number of bytes in 'msgbuf'
1700 * @param timeout when should we time out
1701 * @param session which session must be used (or NULL for "any")
1702 * @param addr the address to use (can be NULL if the plugin
1703 * is "on its own" (i.e. re-use existing TCP connection))
1704 * @param addrlen length of the address in bytes
1705 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1706 * otherwise the plugin may use other addresses or
1707 * existing connections (if available)
1708 * @param cont continuation to call once the message has
1709 * been transmitted (or if the transport is ready
1710 * for the next transmission call; or if the
1711 * peer disconnected...)
1712 * @param cont_cls closure for cont
1713 * @return number of bytes used (on the physical network, with overheads);
1714 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1715 * and does NOT mean that the message was not transmitted (DV)
1718 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1719 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1720 struct GNUNET_TIME_Relative timeout, struct Session *session,
1721 const void *addr, size_t addrlen, int force_address,
1722 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1724 struct Plugin * plugin = cls;
1725 struct PendingMessage * newmsg = NULL;
1726 struct WlanHeader * wlanheader = NULL;
1728 //check if msglen > 0
1729 GNUNET_assert(msgbuf_size > 0);
1731 //get session if needed
1732 if (session == NULL)
1734 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1736 session = get_Session(plugin, addr);
1740 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1741 _("Wlan Address len %d is wrong\n"), addrlen);
1746 //TODO target "problem" not solved
1747 //if (session->target != NULL){
1748 // GNUNET_assert(session->target == *target);
1750 session->target = *target;
1756 //queue message in session
1757 //test if there is no other message in the "queue"
1758 //FIXME: to many send requests
1759 //GNUNET_assert (session->pending_message == NULL);
1760 if (session->pending_message != NULL)
1762 newmsg = session->pending_message;
1764 GNUNET_ERROR_TYPE_ERROR,
1765 "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",
1766 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1767 session->fragment_messages_out_count);
1768 if (session->pending_message2 != NULL)
1771 GNUNET_ERROR_TYPE_ERROR,
1772 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1777 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1778 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1779 wlanheader = (struct WlanHeader *) newmsg->msg;
1780 //copy msg to buffer, not fragmented / segmented yet, but with message header
1781 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1782 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1783 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1784 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1785 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1786 newmsg->transmit_cont = cont;
1787 newmsg->transmit_cont_cls = cont_cls;
1788 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1790 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1792 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1794 if (session->pending_message == NULL)
1796 session->pending_message = newmsg;
1800 session->pending_message2 = newmsg;
1804 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1805 "New message for %p with size (incl wlan header) %u added\n", session,
1806 newmsg->message_size);
1810 queue_Session(plugin, session);
1812 check_fragment_queue(plugin);
1813 //FIXME not the correct size
1819 * function to get the first message in the fragement queue (out) of a session
1820 * @param session pointer to the session
1821 * @return pointer to the struct FragmentMessage
1823 static struct FragmentMessage *
1824 get_fragment_message_from_session(struct Session * session)
1826 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1829 if (fm->session == session)
1839 * function to get the message in the fragement queue (out) of a session with a specific id
1840 * @param session pointer to the session
1841 * @param message_id id of the message
1842 * @return pointer to the struct FragmentMessage
1844 static struct FragmentMessage *
1845 get_fragment_message_from_session_and_id(struct Session * session,
1846 uint32_t message_id)
1848 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1851 if ((fm->session == session) && (fm->message_id_out == message_id))
1861 * Function that can be used to force the plugin to disconnect
1862 * from the given peer and cancel all previous transmissions
1863 * (and their continuation).
1865 * @param cls closure
1866 * @param target peer from which to disconnect
1869 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1871 struct Plugin *plugin = cls;
1872 struct Sessionqueue * queue = plugin->sessions;
1873 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1874 struct PendingMessage * pm = NULL;
1875 struct FragmentMessage * fm;
1876 struct Receive_Message_Queue * receive_queue;
1878 // just look at all the session for the needed one
1879 while (queue != NULL)
1881 // content is never NULL
1882 GNUNET_assert (queue->content != NULL);
1883 if (memcmp(target, &(queue->content->target),
1884 sizeof(struct GNUNET_PeerIdentity)) == 0)
1887 //is this session pending for send
1888 while (pendingsession != NULL)
1890 if (pendingsession->content == queue->content)
1892 plugin->pendingsessions--;
1893 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1894 plugin->pending_Sessions_tail, pendingsession);
1895 GNUNET_free(pendingsession);
1898 pendingsession = pendingsession->next;
1901 //is something of this session in the fragment queue?
1902 fm = get_fragment_message_from_session(queue->content);
1905 free_fragment_message(plugin, fm);
1906 fm = get_fragment_message_from_session(queue->content);
1908 check_next_fragment_timeout(plugin);
1910 //dispose all received fragments
1911 receive_queue = get_receive_message_from_session(plugin,
1913 while (receive_queue != NULL)
1915 free_receive_message(plugin, receive_queue);
1916 receive_queue = get_receive_message_from_session(plugin,
1920 // remove PendingMessage
1921 pm = queue->content->pending_message;
1924 GNUNET_free_non_null(pm->msg);
1928 GNUNET_free(queue->content);
1929 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1931 plugin->session_count--;
1936 queue = queue->next;
1941 * Convert the transports address to a nice, human-readable
1944 * @param cls closure
1945 * @param type name of the transport that generated the address
1946 * @param addr one of the addresses of the host, NULL for the last address
1947 * the specific address format depends on the transport
1948 * @param addrlen length of the address
1949 * @param numeric should (IP) addresses be displayed in numeric form?
1950 * @param timeout after how long should we give up?
1951 * @param asc function to call on each string
1952 * @param asc_cls closure for asc
1955 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1956 const void *addr, size_t addrlen, int numeric,
1957 struct GNUNET_TIME_Relative timeout,
1958 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1961 const unsigned char * input;
1963 //GNUNET_assert(cls !=NULL);
1966 /* invalid address (MAC addresses have 6 bytes) */
1971 input = (const unsigned char*) addr;
1972 GNUNET_snprintf(ret, sizeof(ret),
1973 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1974 input[0], input[1], input[2], input[3], input[4], input[5]);
1979 * Another peer has suggested an address for this
1980 * peer and transport plugin. Check that this could be a valid
1981 * address. If so, consider adding it to the list
1984 * @param cls closure
1985 * @param addr pointer to the address
1986 * @param addrlen length of addr
1987 * @return GNUNET_OK if this is a plausible address for this peer
1992 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1994 //struct Plugin *plugin = cls;
1996 /* check if the address is plausible; if so,
1997 add it to our list! */
1999 GNUNET_assert(cls !=NULL);
2000 //FIXME mitm is not checked
2001 //Mac Address has 6 bytes
2004 /* TODO check for bad addresses like multicast, broadcast, etc */
2008 return GNUNET_SYSERR;
2012 * Function called for a quick conversion of the binary address to
2013 * a numeric address. Note that the caller must not free the
2014 * address and that the next call to this function is allowed
2015 * to override the address again.
2017 * @param cls closure
2018 * @param addr binary address
2019 * @param addrlen length of the address
2020 * @return string representing the same address
2023 wlan_plugin_address_to_string (void *cls,
2027 static char ret[40];
2028 const struct MacAddress *mac;
2030 if (addrlen != sizeof (struct MacAddress))
2036 GNUNET_snprintf(ret, sizeof(ret),
2037 "%s Mac-Address %X:%X:%X:%X:%X:%X",
2039 mac->mac[0], mac->mac[1],
2040 mac->mac[2], mac->mac[3],
2041 mac->mac[4], mac->mac[5]);
2046 * function to check if bitfield is representation of fragments of the message
2047 * @param rec_message message to check
2051 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
2053 uint64_t checkfragments = 0;
2054 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2056 while (rec_queue != NULL)
2058 setBit((char*) &checkfragments, rec_queue->num);
2059 rec_queue = rec_queue->next;
2062 GNUNET_assert(checkfragments == rec_message->received_fragments);
2066 * Function to test if fragment number already exists in the fragments received
2068 * @param rec_message message this fragment belongs to
2069 * @param fh Fragmentheader of the fragment
2070 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2074 is_double_msg(struct Receive_Message_Queue * rec_message,
2075 struct FragmentationHeader * fh)
2077 //test if bitfield is okay
2079 check_message_fragment_bitfield(rec_message);
2082 return testBit((char *) &rec_message->received_fragments, ntohs(
2083 fh->fragment_off_or_num));
2088 * Function to insert a fragment in a queue of a message
2089 * @param session session the fragment belongs to
2090 * @param rec_queue fragment to add
2094 insert_fragment_in_queue(struct Receive_Message_Queue * rec_message,
2095 struct Receive_Fragment_Queue * rec_queue)
2097 GNUNET_assert(rec_message != NULL);
2098 GNUNET_assert(rec_queue != NULL);
2100 struct Receive_Fragment_Queue * rec_queue2 = rec_message->frag_head;
2101 struct WlanHeader * wlanheader = NULL;
2103 //this is the first fragment of the message (fragment id 0)
2104 if (rec_queue->num == 0)
2106 wlanheader = (struct WlanHeader *) rec_queue->msg;
2107 rec_message->rec_size = ntohs(wlanheader->header.size);
2111 while (rec_queue2 != NULL)
2113 if (rec_queue2->num > rec_queue->num)
2115 //next element number is grater than the current num
2116 GNUNET_CONTAINER_DLL_insert_before(rec_message->frag_head, rec_message->frag_tail, rec_queue2, rec_queue);
2117 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2120 rec_queue = rec_queue->next;
2122 //no element has a grater number
2123 GNUNET_CONTAINER_DLL_insert_tail(rec_message->frag_head, rec_message->frag_tail, rec_queue);
2125 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2129 * Function to dispose the fragments received for a message and the message
2130 * @param plugin pointer to the plugin struct
2131 * @param rec_message pointer to the struct holding the message which should be freed
2135 free_receive_message(struct Plugin* plugin,
2136 struct Receive_Message_Queue * rec_message)
2138 GNUNET_assert(rec_message !=NULL);
2139 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2140 struct Receive_Fragment_Queue * rec_queue2;
2142 while (rec_queue != NULL)
2144 rec_queue2 = rec_queue;
2145 rec_queue = rec_queue->next;
2146 GNUNET_free(rec_queue2);
2149 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rec_message);
2151 GNUNET_assert(plugin->pending_receive_messages > 0);
2152 GNUNET_assert(rec_message->session->fragment_messages_in_count > 0);
2154 plugin->pending_receive_messages--;
2155 rec_message->session->fragment_messages_in_count--;
2156 GNUNET_free(rec_message);
2160 * Function to check if all fragments of a message have been received
2161 * @param plugin the plugin handle
2162 * @param session_light information of the message sender
2163 * @param session session the message belongs to
2164 * @param rec_message pointer to the message that should be checked
2168 check_rec_finished_msg(struct Plugin* plugin,
2169 struct Session_light * session_light, struct Session * session,
2170 struct Receive_Message_Queue * rec_message)
2172 GNUNET_assert(rec_message !=NULL);
2174 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2175 int packetsize = rec_message->rec_size;
2178 uint64_t bitfield = 0;
2181 //check if first fragment is present
2182 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2186 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2187 else if (packetsize < sizeof(struct WlanHeader)
2188 + sizeof(struct GNUNET_MessageHeader))
2191 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2192 "Message not big enough\n");
2194 free_receive_message(plugin, rec_message);
2199 check_message_fragment_bitfield(rec_message);
2202 bitfield = ~bitfield;
2203 bitfield = bitfield >> (63 - rec_message->frag_tail->num);
2204 if (rec_message->received_fragments == bitfield)
2207 while (rec_queue != NULL)
2209 sum += rec_queue->size;
2210 rec_queue = rec_queue->next;
2212 //sum should always be smaller or equal of
2213 GNUNET_assert(sum <= packetsize);
2214 if (sum == packetsize)
2218 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2219 "check_rec_finished_msg: A message for %p is complete\n", session);
2223 //copy fragments together
2224 msg = GNUNET_malloc(packetsize);
2225 rec_queue = rec_message->frag_head;
2227 while (rec_queue != NULL)
2229 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2230 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
2231 aktnum += rec_queue->size;
2232 rec_queue = rec_queue->next;
2234 free_receive_message(plugin, rec_message);
2235 //call wlan_process_helper to process the message
2236 wlan_data_massage_handler(plugin, session_light,
2237 (struct GNUNET_MessageHeader*) msg);
2238 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2246 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2249 GNUNET_assert(client != NULL);
2250 GNUNET_assert(cls != NULL);
2251 struct Session * session = (struct Session *) client;
2252 struct Plugin * plugin = (struct Plugin *) cls;
2254 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2255 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2256 distance[0].value = htonl(1);
2257 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2258 distance[1].value = htonl(0);
2261 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2262 "Calling plugin->env->receive for session %p; %s\n", session,
2263 wlan_plugin_address_to_string(NULL, session->addr, 6));
2266 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2267 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2268 session->addr, sizeof(session->addr));
2272 * handels the data after all fragments are put together
2274 * @param session_light
2275 * @param hdr pointer to the data
2278 wlan_data_massage_handler(struct Plugin * plugin,
2279 struct Session_light * session_light,
2280 const struct GNUNET_MessageHeader * hdr)
2282 struct WlanHeader * wlanheader = NULL;
2283 struct Session * session = NULL;
2284 const char * tempmsg = NULL;
2285 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2286 struct GNUNET_PeerIdentity tmptarget;
2288 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2293 GNUNET_ERROR_TYPE_DEBUG,
2294 "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2298 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2299 + sizeof(struct GNUNET_MessageHeader))
2301 //packet not big enought
2305 GNUNET_assert(session_light != NULL);
2306 if (session_light->session == NULL)
2308 session_light->session = search_session(plugin, session_light->addr);
2310 session = session_light->session;
2311 wlanheader = (struct WlanHeader *) hdr;
2313 tempmsg = (char*) &wlanheader[1];
2314 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2316 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2319 //wrong crc, dispose message
2320 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2321 "Wlan message Header crc was wrong\n");
2325 //if not in session list
2326 if (session == NULL)
2330 GNUNET_ERROR_TYPE_DEBUG,
2331 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2332 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2333 sizeof(struct WlanHeader));
2335 //try if it is a hello message
2336 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2337 + sizeof(struct WlanHeader))
2339 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2341 if (GNUNET_HELLO_get_id(
2342 (const struct GNUNET_HELLO_Message *) temp_hdr,
2343 &tmptarget) == GNUNET_OK)
2345 session = create_session(plugin, session_light->addr);
2346 session_light->session = session;
2347 memcpy(&session->target, &tmptarget,
2348 sizeof(struct GNUNET_PeerIdentity));
2352 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2353 "WLAN client not in session list and hello message not okay\n");
2360 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2361 "WLAN client not in session list and not a hello message\n");
2368 GNUNET_ERROR_TYPE_WARNING,
2369 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2370 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2371 sizeof(struct WlanHeader));
2376 //"receive" the message
2379 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2380 (const char *) temp_hdr,
2381 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2387 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2388 "wlan_data_massage_handler got wrong message type\n");
2394 * function to add an ack to send it for a received fragment
2395 * @param plugin pointer to the global plugin structure
2396 * @param session pointer to the session this ack belongs to
2397 * @param bitfield bitfield to send
2398 * @param fh pointer to the fragmentation header which we would like to acknolage
2402 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2403 uint64_t bitfield, struct FragmentationHeader * fh)
2405 struct AckSendQueue * ack;
2407 GNUNET_assert(plugin != NULL);
2408 GNUNET_assert(session != NULL);
2409 GNUNET_assert(fh != NULL);
2411 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2412 ack->fragments_field = bitfield;
2413 ack->message_id = ntohl(fh->message_id);
2414 ack->session = session;
2416 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2417 plugin->ack_send_queue_tail, ack);
2422 * function to get the receive message from the message id and the session
2423 * @param plugin pointer to the plugin struct
2424 * @param session session this fragment belongs to
2425 * @param message_id id of the message
2428 struct Receive_Message_Queue *
2429 get_receive_message(struct Plugin * plugin, struct Session * session,
2430 uint32_t message_id)
2432 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2433 while (rec_message != NULL)
2435 if ((rec_message->message_id_in == message_id) && (rec_message->session
2440 rec_message = rec_message->next;
2446 * function to get the receive message of a session
2447 * @param plugin pointer to the plugin struct
2448 * @param session session this fragment belongs to
2451 struct Receive_Message_Queue *
2452 get_receive_message_from_session(struct Plugin * plugin,
2453 struct Session * session)
2455 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2456 while (rec_message != NULL)
2458 if (rec_message->session == session)
2462 rec_message = rec_message->next;
2468 * function to insert a received fragment into the right fragment queue of the right message
2469 * @param plugin pointer to the plugin struct
2470 * @param session_light pointer to the session_light struct of this message
2471 * @param session session this fragment belongs to
2472 * @param fh pointer to the header of the fragment
2473 * @return new fragment bitfield for the message
2477 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2478 struct Session_light * session_light, struct Session * session,
2479 struct FragmentationHeader * fh)
2481 struct Receive_Fragment_Queue * rec_queue = NULL;
2482 struct Receive_Message_Queue * rec_message;
2483 const char * tempmsg = (char*) &fh[1];
2484 uint64_t retval = 0;
2486 //TODO fragments do not timeout
2487 //check if message_id is right or it is a new msg
2488 GNUNET_assert(fh != NULL);
2490 rec_message = get_receive_message(plugin, session, ntohs(fh->message_id));
2492 if (rec_message == NULL)
2494 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2497 //new message incoming
2498 rec_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2499 rec_message->message_id_in = ntohs(fh->message_id);
2500 rec_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2501 rec_message->session = session;
2502 rec_message->timeout = GNUNET_TIME_absolute_add(
2503 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2504 rec_message->received_fragments = 0;
2506 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rec_message);
2508 session->fragment_messages_in_count++;
2509 plugin->pending_receive_messages++;
2513 GNUNET_ERROR_TYPE_DEBUG,
2514 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2515 rec_message->message_id_in, session->fragment_messages_in_count,
2516 plugin->pending_receive_messages);
2523 GNUNET_ERROR_TYPE_INFO,
2524 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2525 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2530 if (is_double_msg(rec_message, fh) != GNUNET_YES)
2534 rec_queue = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2535 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2536 rec_queue->size = ntohs(fh->header.size)
2537 - sizeof(struct FragmentationHeader);
2538 rec_queue->num = ntohs(fh->fragment_off_or_num);
2539 rec_queue->msg = (char*) &(rec_queue[1]);
2540 //copy msg to buffer
2541 memcpy((char *) rec_queue->msg, tempmsg, rec_queue->size);
2542 insert_fragment_in_queue(rec_message, rec_queue);
2544 retval = rec_message->received_fragments;
2548 GNUNET_ERROR_TYPE_DEBUG,
2549 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2550 rec_message->rec_size, rec_queue->size,
2551 rec_message->received_fragments, rec_message->message_id_in, session);
2554 check_rec_finished_msg(plugin, session_light, session, rec_message);
2558 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2559 retval = rec_message->received_fragments;
2567 * Function used for to process the data received from the wlan interface
2569 * @param cls the plugin handle
2570 * @param session_light FIXME: document
2571 * @param hdr hdr of the GNUNET_MessageHeader
2574 wlan_data_helper(void *cls, struct Session_light * session_light,
2575 const struct GNUNET_MessageHeader * hdr)
2577 struct Plugin *plugin = cls;
2578 struct Session * session = NULL;
2580 struct FragmentationHeader * fh = NULL;
2581 struct FragmentationAckHeader * fah = NULL;
2582 struct FragmentMessage * fm = NULL;
2584 const char * tempmsg = NULL;
2586 uint64_t fragment_bitfield = 0;
2589 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2592 //TODO better DOS protection, error handling
2593 //TODO test first than create session
2594 GNUNET_assert(session_light != NULL);
2598 GNUNET_ERROR_TYPE_DEBUG,
2599 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2600 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2601 session_light->addr, 6));
2604 if (session_light->session == NULL)
2606 session_light->session = get_Session(plugin, session_light->addr);
2608 GNUNET_assert(GNUNET_HELLO_get_id(
2609 (const struct GNUNET_HELLO_Message *) &hdr[1],
2610 &(session_light->session->target) ) != GNUNET_SYSERR);
2615 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2618 GNUNET_assert(session_light != NULL);
2619 if (session_light->session == NULL)
2621 session_light->session = search_session(plugin, session_light->addr);
2623 session = session_light->session;
2625 fh = (struct FragmentationHeader *) hdr;
2626 tempmsg = (char*) &fh[1];
2630 GNUNET_ERROR_TYPE_DEBUG,
2631 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2632 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2633 hdr->size), wlan_plugin_address_to_string(NULL,
2634 session_light->addr, 6));
2637 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2639 //wrong crc, dispose message
2640 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2644 //if in the session list
2645 if (session != NULL)
2647 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2648 session_light, session, fh);
2654 GNUNET_ERROR_TYPE_INFO,
2655 "WLAN client not in session list, fragment num %u, message id %u\n",
2656 ntohs(fh->fragment_off_or_num), ntohs(fh->message_id));
2657 wlan_data_massage_handler(plugin, session_light,
2658 (struct GNUNET_MessageHeader *) tempmsg);
2659 session = session_light->session;
2660 //test if a session was created
2661 if (session == NULL)
2665 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2668 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2669 check_next_fragment_timeout(plugin);
2674 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2679 GNUNET_ERROR_TYPE_DEBUG,
2680 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2681 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2682 session_light->addr, 6));
2685 GNUNET_assert(session_light != NULL);
2686 if (session_light->session == NULL)
2688 session_light->session = search_session(plugin, session_light->addr);
2689 GNUNET_assert(session_light->session != NULL);
2691 session = session_light->session;
2692 fah = (struct FragmentationAckHeader *) hdr;
2693 fm = get_fragment_message_from_session_and_id(session, ntohl(
2698 fm->ack_bitfield = fm->ack_bitfield | ntohll(fah->fragment_field);
2699 check_finished_fragment(plugin, fm);
2703 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2704 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2713 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2714 "WLAN packet inside the WLAN helper packet has not the right type\n");
2719 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2720 "Helper finished\n");
2727 macprinter(const u_int8_t * mac)
2729 static char macstr[20];
2731 GNUNET_snprintf (macstr,
2733 "%X:%X:%X:%X:%X:%X",
2734 mac[0], mac[1], mac[2],
2735 mac[3], mac[4], mac[5]);
2741 * Function used for to process the data from the suid process
2743 * @param cls the plugin handle
2744 * @param client client that send the data (not used)
2745 * @param hdr header of the GNUNET_MessageHeader
2748 wlan_process_helper (void *cls,
2750 const struct GNUNET_MessageHeader *hdr)
2752 struct Plugin *plugin = cls;
2753 struct ieee80211_frame * wlanIeeeHeader = NULL;
2754 struct Session_light * session_light = NULL;
2755 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2760 switch (ntohs(hdr->type))
2762 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2764 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2765 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2769 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2770 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader))
2773 /* FIXME: restart SUID process */
2776 wlanIeeeHeader = (struct ieee80211_frame *) &hdr[1];
2778 //process only if it is an broadcast or for this computer both with the gnunet bssid
2781 if (memcmp(&(wlanIeeeHeader->i_addr3), mac_bssid,
2782 sizeof(struct MacAddress)) == 0)
2784 //check for broadcast or mac
2785 if (memcmp(&(wlanIeeeHeader->i_addr1), bc_all_mac,
2786 sizeof(struct MacAddress) == 0) || memcmp(
2787 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2788 sizeof(struct MacAddress)) == 0)
2791 // process the inner data
2794 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2795 - sizeof(struct GNUNET_MessageHeader);
2797 session_light = GNUNET_malloc(sizeof(struct Session_light));
2798 memcpy(session_light->addr, &(wlanIeeeHeader->i_addr2),
2799 sizeof(struct MacAddress));
2800 //session_light->session = search_session(plugin,session_light->addr);
2803 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2804 while (pos < datasize)
2806 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2809 wlan_data_helper(plugin, session_light, temp_hdr);
2810 pos += ntohs(temp_hdr->size);
2815 GNUNET_free(session_light);
2820 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2821 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2822 wlanIeeeHeader->i_addr1));
2829 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2830 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2831 wlanIeeeHeader->i_addr2));
2835 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2836 //TODO more control messages
2837 //TODO use struct wlan_helper_control
2838 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2841 /* FIXME: restart SUID process */
2844 memcpy (&plugin->mac_address,
2846 sizeof(struct MacAddress));
2848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2849 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2850 wlan_plugin_address_to_string (cls,
2851 &plugin->mac_address,
2852 sizeof (struct MacAddress)));
2854 plugin->env->notify_address(plugin->env->cls, "wlan",
2855 &plugin->mac_address, sizeof(struct MacAddress),
2856 GNUNET_TIME_UNIT_FOREVER_REL);
2866 * We have been notified that wlan-helper has written something to stdout.
2867 * Handle the output, then reschedule this function to be called again once
2868 * more is available.
2870 * @param cls the plugin handle
2871 * @param tc the scheduling context
2874 wlan_plugin_helper_read(void *cls,
2875 const struct GNUNET_SCHEDULER_TaskContext *tc)
2877 struct Plugin *plugin = cls;
2878 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2883 "Start reading from STDIN\n");
2886 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2889 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2892 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2897 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2898 _("Finished reading from wlan-helper stdout with code: %d\n"),
2903 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2904 GNUNET_NO, GNUNET_NO);
2906 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2907 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2908 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2909 &wlan_plugin_helper_read, plugin);
2913 * Start the gnunet-wlan-helper process.
2915 * @param plugin the transport plugin
2916 * @param testmode should we use the dummy driver for testing?
2917 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2920 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2922 const char * filename = "gnunet-transport-wlan-helper";
2923 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2924 if (plugin->server_stdout == NULL)
2925 return GNUNET_SYSERR;
2927 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2928 if (plugin->server_stdin == NULL)
2929 return GNUNET_SYSERR;
2932 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2933 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2934 plugin->interface, testmode);
2936 /* Start the server process */
2938 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2939 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2940 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2941 if (plugin->server_proc == NULL)
2944 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2945 "Failed to start gnunet-wlan-helper process\n");
2947 return GNUNET_SYSERR;
2950 /* Close the write end of the read pipe */
2951 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2953 /* Close the read end of the write pipe */
2954 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2956 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2957 GNUNET_DISK_PIPE_END_READ);
2958 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2959 GNUNET_DISK_PIPE_END_WRITE);
2961 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2964 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2965 "Adding server_read_task for the wlan-helper\n");
2970 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2971 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2972 &wlan_plugin_helper_read, plugin);
2978 * Exit point from the plugin.
2979 * @param cls pointer to the api struct
2984 libgnunet_plugin_transport_wlan_done(void *cls)
2986 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2987 struct Plugin *plugin = api->cls;
2990 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2991 "libgnunet_plugin_transport_wlan_done started\n");
2994 GNUNET_assert(cls !=NULL);
2996 if (plugin->suid_tokenizer != NULL)
2997 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2999 if (plugin->data_tokenizer != NULL)
3000 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3002 GNUNET_free_non_null(plugin->interface);
3003 GNUNET_free (plugin);
3009 * Entry point for the plugin.
3011 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3012 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3015 libgnunet_plugin_transport_wlan_init(void *cls)
3017 //struct GNUNET_SERVICE_Context *service;
3018 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3019 struct GNUNET_TRANSPORT_PluginFunctions *api;
3020 struct Plugin *plugin;
3021 static unsigned long long testmode = 0;
3023 GNUNET_assert(cls !=NULL);
3025 plugin = GNUNET_malloc (sizeof (struct Plugin));
3027 plugin->pendingsessions = 0;
3028 plugin->session_count = 0;
3029 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3030 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3031 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3033 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3036 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3038 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3039 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3041 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3043 api->send = &wlan_plugin_send;
3044 api->disconnect = &wlan_plugin_disconnect;
3045 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3046 api->check_address = &wlan_plugin_address_suggested;
3047 api->address_to_string = &wlan_plugin_address_to_string;
3051 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3053 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3054 "transport-wlan", "TESTMODE", &testmode))
3055 testmode = 0; //default value
3058 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3060 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3061 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3063 libgnunet_plugin_transport_wlan_done(api);
3069 set_next_beacon_time(plugin);
3071 wlan_transport_start_wlan_helper(plugin, testmode);
3073 start_next_message_id();
3076 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3082 /* end of plugin_transport_wlan.c */