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;
977 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
980 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
982 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
983 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
985 fm = plugin->pending_Fragment_Messages_head;
987 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
989 //check if some acks are in the queue
990 if (plugin->ack_send_queue_head != NULL)
992 next_send = GNUNET_TIME_relative_get_zero();
994 //check if there are some fragments in the queue
998 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
1000 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1001 &delay_fragment_task, plugin);
1006 * Function to get the next queued Session, removes the session from the queue
1009 static struct Session *
1010 get_next_queue_Session(struct Plugin * plugin)
1012 struct Session * session;
1013 struct Sessionqueue * sessionqueue;
1014 struct Sessionqueue * sessionqueue_alt;
1015 struct PendingMessage * pm;
1016 sessionqueue = plugin->pending_Sessions;
1017 while (sessionqueue != NULL)
1019 session = sessionqueue->content;
1021 pm = session->pending_message;
1025 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1026 "pending message is empty, should not happen. session %p\n",
1030 GNUNET_assert(pm != NULL);
1032 //check for message timeout
1033 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1035 //check if session has no message in the fragment queue
1036 if (session->fragment_messages_out_count
1037 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1039 plugin->pendingsessions--;
1040 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1041 plugin->pending_Sessions_tail, sessionqueue);
1042 GNUNET_free(sessionqueue);
1048 sessionqueue = sessionqueue->next;
1054 session->pending_message = session->pending_message2;
1055 session->pending_message2 = NULL;
1057 //call the cont func that it did not work
1058 if (pm->transmit_cont != NULL)
1059 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1061 GNUNET_free(pm->msg);
1064 if (session->pending_message == NULL)
1066 sessionqueue_alt = sessionqueue;
1067 sessionqueue = sessionqueue->next;
1068 plugin->pendingsessions--;
1069 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1070 plugin->pending_Sessions_tail, sessionqueue_alt);
1072 GNUNET_free(sessionqueue_alt);
1082 * Function to sort the message into the message fragment queue
1083 * @param plugin the plugin struct
1084 * @param fm message to sort into the queue
1087 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
1089 struct FragmentMessage * fm2;
1090 //sort into the list at the right position
1092 fm2 = plugin->pending_Fragment_Messages_head;
1096 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
1107 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
1108 plugin->pending_Fragment_Messages_tail,fm2,fm);
1112 * frees the space of a message in the fragment queue (send queue)
1113 * @param plugin the plugin struct
1114 * @param fm message to free
1117 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1121 (fm->session->fragment_messages_out_count)--;
1122 GNUNET_free_non_null(fm->msg);
1123 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1124 plugin->pending_Fragment_Messages_tail, fm);
1126 plugin->pending_fragment_messages--;
1129 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1130 "free pending fragment messages, pending messages remaining %u\n",
1131 plugin->pending_fragment_messages);
1137 * Function to check if there is some space in the fragment queue
1138 * inserts a message if space is available
1139 * @param plugin the plugin struct
1143 check_fragment_queue(struct Plugin * plugin)
1145 struct Session * session;
1146 struct FragmentMessage * fm;
1147 struct GNUNET_PeerIdentity pid;
1149 struct PendingMessage * pm;
1151 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
1153 session = get_next_queue_Session(plugin);
1154 if (session != NULL)
1156 pm = session->pending_message;
1157 session->pending_message = NULL;
1158 session->fragment_messages_out_count++;
1159 GNUNET_assert(pm != NULL);
1161 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1162 fm->message_size = pm->message_size;
1164 fm->session = session;
1165 fm->timeout.abs_value = pm->timeout.abs_value;
1166 fm->message_pos = 0;
1167 fm->next_ack = GNUNET_TIME_absolute_get();
1168 fm->message_id_out = get_next_message_id();
1169 fm->ack_bitfield = 0;
1171 sort_fragment_into_queue(plugin, fm);
1172 plugin->pending_fragment_messages++;
1174 if (pm->transmit_cont != NULL)
1176 pid = session->target;
1177 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1180 "called pm->transmit_cont for %p\n", session);
1186 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1187 "no pm->transmit_cont for %p\n", session);
1192 if (session->pending_message2 != NULL)
1194 session->pending_message = session->pending_message2;
1195 session->pending_message2 = NULL;
1197 queue_Session(plugin, session);
1200 //check if timeout changed
1201 check_next_fragment_timeout(plugin);
1207 * Funktion to check if all fragments where send and the acks received
1208 * frees the space if finished
1209 * @param plugin the plugin struct
1210 * @param fm the message to check
1213 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1215 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1216 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1217 - sizeof(struct FragmentationHeader)));
1218 uint64_t tmpfield = 0xFFFFFFFFFFFFFFFF;
1219 tmpfield = tmpfield >> maxack;
1223 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1224 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1225 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1228 if (fm->ack_bitfield == tmpfield)
1231 free_fragment_message(plugin, fm);
1234 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1235 "Finished sending and got all acks for a fragmented message\n");
1238 check_next_fragment_timeout(plugin);
1239 check_fragment_queue(plugin);
1245 * Function to set the next fragment number
1246 * @param fm use this FragmentMessage
1250 set_next_message_fragment_pos(struct FragmentMessage * fm)
1253 //check if retransmit is needed
1254 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1257 // be positive and try again later :-D
1258 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1259 // find first missing fragment
1261 fm->message_pos = 0;
1264 //test if ack 0 (or X) was already received
1265 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1273 send_hello_beacon(struct Plugin * plugin)
1277 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1282 struct GNUNET_MessageHeader * msgheader = NULL;
1283 struct ieee80211_frame * ieeewlanheader = NULL;
1284 struct Radiotap_Send * radioHeader = NULL;
1285 struct GNUNET_MessageHeader * msgheader2 = NULL;
1287 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1288 *(plugin->env->our_hello)) <= WLAN_MTU);
1289 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1290 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1291 + GNUNET_HELLO_size(*(plugin->env->our_hello));
1293 msgheader = GNUNET_malloc(size);
1294 msgheader->size = htons(size);
1295 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1297 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1298 getRadiotapHeader(plugin, NULL, radioHeader);
1299 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1300 getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
1302 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1303 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1304 + sizeof(struct GNUNET_MessageHeader));
1306 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1307 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1308 *(plugin->env->our_hello)));
1310 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1312 if (bytes == GNUNET_SYSERR)
1314 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1315 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1316 errno, strerror(errno));
1319 GNUNET_assert(bytes != GNUNET_SYSERR);
1320 GNUNET_assert(bytes == size);
1321 GNUNET_free(msgheader);
1323 set_next_beacon_time(plugin);
1324 check_next_fragment_timeout(plugin);
1328 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1333 struct GNUNET_MessageHeader * msgheader = NULL;
1334 struct ieee80211_frame * ieeewlanheader = NULL;
1335 struct Radiotap_Send * radioHeader = NULL;
1336 struct FragmentationAckHeader * msgheader2 = NULL;
1338 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1341 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1342 "Sending ack for message_id %u with fragment field %u\n",
1343 ack->message_id, ack->fragments_field);
1346 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1347 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1348 msgheader = GNUNET_malloc(size);
1349 msgheader->size = htons(size);
1350 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1352 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1353 getRadiotapHeader(plugin, ack->session, radioHeader);
1354 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1355 getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
1357 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1358 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1359 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1360 msgheader2->message_id = htonl(ack->message_id);
1361 msgheader2->fragment_field = htonll(ack->fragments_field);
1363 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1364 if (bytes == GNUNET_SYSERR)
1366 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1367 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1368 errno, strerror(errno));
1371 GNUNET_assert(bytes != GNUNET_SYSERR);
1372 GNUNET_assert(bytes == size);
1373 GNUNET_free(msgheader);
1374 check_next_fragment_timeout(plugin);
1378 * Function called when wlan helper is ready to get some data
1380 * @param cls closure
1381 * @param tc GNUNET_SCHEDULER_TaskContext
1385 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1388 struct Plugin * plugin = cls;
1389 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1391 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1394 struct Session * session = NULL;
1395 struct FragmentMessage * fm = NULL;
1396 struct ieee80211_frame * ieeewlanheader = NULL;
1397 struct Radiotap_Send * radioHeader = NULL;
1398 struct GNUNET_MessageHeader * msgheader = NULL;
1400 struct FragmentationHeader fragheader;
1401 struct FragmentationHeader * fragheaderptr = NULL;
1402 struct Finish_send * finish = NULL;
1403 struct AckSendQueue * ack;
1406 const char * copystart = NULL;
1407 uint16_t copysize = 0;
1408 uint copyoffset = 0;
1410 if (plugin->ack_send_queue_head != NULL)
1412 ack = plugin->ack_send_queue_head;
1413 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1414 plugin->ack_send_queue_tail, ack);
1415 send_ack(plugin, ack);
1420 //test if a "hello-beacon" has to be send
1421 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1423 send_hello_beacon(plugin);
1429 fm = plugin->pending_Fragment_Messages_head;
1432 session = fm->session;
1433 GNUNET_assert(session != NULL);
1435 // test if message timed out
1436 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1439 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1442 check_fragment_queue(plugin);
1443 free_fragment_message(plugin, fm);
1449 //if (fm->message_size > WLAN_MTU)
1451 size += sizeof(struct FragmentationHeader);
1453 set_next_message_fragment_pos(fm);
1455 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1460 GNUNET_ERROR_TYPE_DEBUG,
1461 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1462 fm->message_id_out, fm->message_pos, copysize
1463 + sizeof(struct FragmentationHeader), copyoffset,
1464 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1467 fragheader.fragment_off_or_num = htons(fm->message_pos);
1468 fragheader.message_id = htonl(fm->message_id_out);
1469 copystart = fm->msg + copyoffset;
1470 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1471 WLAN_MTU - sizeof(struct FragmentationHeader));
1473 if (copyoffset >= fm->message_size)
1476 GNUNET_ERROR_TYPE_ERROR,
1477 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1478 copyoffset, fm->message_size, WLAN_MTU
1479 - sizeof(struct FragmentationHeader), copysize,
1482 GNUNET_assert(copyoffset < fm->message_size);
1483 //FIXME remove later
1484 GNUNET_assert(copystart < fm->msg + fm->message_size);
1486 fragheader.header.size = htons(copysize
1487 + sizeof(struct FragmentationHeader));
1488 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1493 // there is no need to split
1494 copystart = fm->msg;
1495 copysize = fm->message_size;
1499 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1500 + sizeof(struct GNUNET_MessageHeader);
1501 msgheader = GNUNET_malloc(size);
1502 msgheader->size = htons(size);
1503 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1505 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1506 getRadiotapHeader(plugin, session, radioHeader);
1508 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1509 getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
1511 //could be faster if content is just send and not copyed before
1512 //fragmentheader is needed
1513 //if (fm->message_size > WLAN_MTU)
1515 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1516 memcpy(&ieeewlanheader[1], &fragheader,
1517 sizeof(struct FragmentationHeader));
1518 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1519 memcpy(&fragheaderptr[1], copystart, copysize);
1523 memcpy(&ieeewlanheader[1], copystart, copysize);
1526 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1528 if (bytes == GNUNET_SYSERR)
1531 GNUNET_ERROR_TYPE_ERROR,
1532 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1533 errno, strerror(errno));
1536 GNUNET_assert(bytes != GNUNET_SYSERR);
1540 finish = GNUNET_malloc(sizeof( struct Finish_send));
1541 finish->plugin = plugin;
1542 finish->msgheader = (char *) msgheader + bytes;
1543 finish->size = size - bytes;
1544 finish->msgstart = msgheader;
1546 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1548 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1549 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1550 &finish_sending, finish);
1555 GNUNET_assert(bytes == size);
1557 GNUNET_free(msgheader);
1558 check_next_fragment_timeout(plugin);
1561 //check if this was the last fragment of this message, if true then queue at the end of the list
1562 if (copysize + copyoffset >= fm->message_size)
1564 GNUNET_assert(copysize + copyoffset == fm->message_size);
1566 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1567 plugin->pending_Fragment_Messages_tail, fm);
1569 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1570 plugin->pending_Fragment_Messages_tail, fm);
1571 // if fragments have opimized timeouts
1572 //sort_fragment_into_queue(plugin,fm);
1579 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1580 "do_transmit did nothing, should not happen!\n");
1584 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1586 struct Finish_send * finish;
1587 struct Plugin * plugin;
1591 plugin = finish->plugin;
1593 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1595 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1596 finish->msgheader, finish->size);
1597 GNUNET_assert(bytes != GNUNET_SYSERR);
1599 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1600 if (bytes != finish->size)
1603 finish->plugin = plugin;
1604 finish->msgheader = finish->msgheader + bytes;
1605 finish->size = finish->size - bytes;
1606 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1607 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1608 &finish_sending, finish);
1612 GNUNET_free(finish->msgstart);
1613 GNUNET_free(finish);
1614 check_next_fragment_timeout(plugin);
1620 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1621 struct Radiotap_Send * header)
1624 header->rate = session->rate;
1625 header->tx_power = session->tx_power;
1626 header->antenna = session->antenna;
1632 * function to generate the wlan hardware header for one packet
1633 * @param Header address to write the header to
1634 * @param to_mac_addr address of the recipient
1635 * @param plugin pointer to the plugin struct
1636 * @return GNUNET_YES if there was no error
1640 getWlanHeader(struct ieee80211_frame * Header, const char * const to_mac_addr,
1641 struct Plugin * plugin)
1643 memcpy(&Header->i_addr3, mac_bssid, sizeof(mac_bssid));
1644 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1645 memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1652 * @param msgbuf pointer tor the data
1653 * @param msgbuf_size size of the data
1655 * @return 32bit crc value
1659 getcrc32(const char *msgbuf, size_t msgbuf_size)
1661 //TODO calc some crc
1668 * @param msgbuf pointer tor the data
1669 * @param msgbuf_size size of the data
1671 * @return 16bit crc value
1675 getcrc16(const char *msgbuf, size_t msgbuf_size)
1677 //TODO calc some crc
1682 * Function that can be used by the transport service to transmit
1683 * a message using the plugin.
1685 * @param cls closure
1686 * @param target who should receive this message
1687 * @param priority how important is the message
1688 * @param msgbuf the message to transmit
1689 * @param msgbuf_size number of bytes in 'msgbuf'
1690 * @param timeout when should we time out
1691 * @param session which session must be used (or NULL for "any")
1692 * @param addr the address to use (can be NULL if the plugin
1693 * is "on its own" (i.e. re-use existing TCP connection))
1694 * @param addrlen length of the address in bytes
1695 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1696 * otherwise the plugin may use other addresses or
1697 * existing connections (if available)
1698 * @param cont continuation to call once the message has
1699 * been transmitted (or if the transport is ready
1700 * for the next transmission call; or if the
1701 * peer disconnected...)
1702 * @param cont_cls closure for cont
1703 * @return number of bytes used (on the physical network, with overheads);
1704 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1705 * and does NOT mean that the message was not transmitted (DV)
1708 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1709 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1710 struct GNUNET_TIME_Relative timeout, struct Session *session,
1711 const void *addr, size_t addrlen, int force_address,
1712 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1714 struct Plugin * plugin = cls;
1715 struct PendingMessage * newmsg = NULL;
1716 struct WlanHeader * wlanheader = NULL;
1718 //check if msglen > 0
1719 GNUNET_assert(msgbuf_size > 0);
1721 //get session if needed
1722 if (session == NULL)
1724 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1726 session = get_Session(plugin, addr);
1730 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1731 _("Wlan Address len %d is wrong\n"), addrlen);
1736 //TODO target "problem" not solved
1737 //if (session->target != NULL){
1738 // GNUNET_assert(session->target == *target);
1740 session->target = *target;
1746 //queue message in session
1747 //test if there is no other message in the "queue"
1748 //FIXME: to many send requests
1749 //GNUNET_assert (session->pending_message == NULL);
1750 if (session->pending_message != NULL)
1752 newmsg = session->pending_message;
1754 GNUNET_ERROR_TYPE_ERROR,
1755 "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",
1756 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1757 session->fragment_messages_out_count);
1758 if (session->pending_message2 != NULL)
1761 GNUNET_ERROR_TYPE_ERROR,
1762 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1767 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1768 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1769 wlanheader = (struct WlanHeader *) newmsg->msg;
1770 //copy msg to buffer, not fragmented / segmented yet, but with message header
1771 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1772 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1773 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1774 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1775 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1776 newmsg->transmit_cont = cont;
1777 newmsg->transmit_cont_cls = cont_cls;
1778 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1780 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1782 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1784 if (session->pending_message == NULL)
1786 session->pending_message = newmsg;
1790 session->pending_message2 = newmsg;
1794 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1795 "New message for %p with size (incl wlan header) %u added\n", session,
1796 newmsg->message_size);
1800 queue_Session(plugin, session);
1802 check_fragment_queue(plugin);
1803 //FIXME not the correct size
1809 * function to get the first message in the fragement queue (out) of a session
1810 * @param session pointer to the session
1811 * @return pointer to the struct FragmentMessage
1813 static struct FragmentMessage *
1814 get_fragment_message_from_session(struct Session * session)
1816 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1819 if (fm->session == session)
1829 * function to get the message in the fragement queue (out) of a session with a specific id
1830 * @param session pointer to the session
1831 * @param message_id id of the message
1832 * @return pointer to the struct FragmentMessage
1834 static struct FragmentMessage *
1835 get_fragment_message_from_session_and_id(struct Session * session,
1836 uint32_t message_id)
1838 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1841 if ((fm->session == session) && (fm->message_id_out == message_id))
1851 * Function that can be used to force the plugin to disconnect
1852 * from the given peer and cancel all previous transmissions
1853 * (and their continuation).
1855 * @param cls closure
1856 * @param target peer from which to disconnect
1859 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1861 struct Plugin *plugin = cls;
1862 struct Sessionqueue * queue = plugin->sessions;
1863 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1864 struct PendingMessage * pm = NULL;
1865 struct FragmentMessage * fm;
1866 struct Receive_Message_Queue * receive_queue;
1868 // just look at all the session for the needed one
1869 while (queue != NULL)
1871 // content is never NULL
1872 GNUNET_assert (queue->content != NULL);
1873 if (memcmp(target, &(queue->content->target),
1874 sizeof(struct GNUNET_PeerIdentity)) == 0)
1877 //is this session pending for send
1878 while (pendingsession != NULL)
1880 if (pendingsession->content == queue->content)
1882 plugin->pendingsessions--;
1883 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1884 plugin->pending_Sessions_tail, pendingsession);
1885 GNUNET_free(pendingsession);
1888 pendingsession = pendingsession->next;
1891 //is something of this session in the fragment queue?
1892 fm = get_fragment_message_from_session(queue->content);
1895 free_fragment_message(plugin, fm);
1896 fm = get_fragment_message_from_session(queue->content);
1898 check_next_fragment_timeout(plugin);
1900 //dispose all received fragments
1901 receive_queue = get_receive_message_from_session(plugin,
1903 while (receive_queue != NULL)
1905 free_receive_message(plugin, receive_queue);
1906 receive_queue = get_receive_message_from_session(plugin,
1910 // remove PendingMessage
1911 pm = queue->content->pending_message;
1914 GNUNET_free_non_null(pm->msg);
1918 GNUNET_free(queue->content);
1919 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1921 plugin->session_count--;
1926 queue = queue->next;
1931 * Convert the transports address to a nice, human-readable
1934 * @param cls closure
1935 * @param type name of the transport that generated the address
1936 * @param addr one of the addresses of the host, NULL for the last address
1937 * the specific address format depends on the transport
1938 * @param addrlen length of the address
1939 * @param numeric should (IP) addresses be displayed in numeric form?
1940 * @param timeout after how long should we give up?
1941 * @param asc function to call on each string
1942 * @param asc_cls closure for asc
1945 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1946 const void *addr, size_t addrlen, int numeric,
1947 struct GNUNET_TIME_Relative timeout,
1948 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1951 const unsigned char * input;
1953 //GNUNET_assert(cls !=NULL);
1956 /* invalid address (MAC addresses have 6 bytes) */
1961 input = (const unsigned char*) addr;
1962 GNUNET_snprintf(ret, sizeof(ret),
1963 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1964 input[0], input[1], input[2], input[3], input[4], input[5]);
1969 * Another peer has suggested an address for this
1970 * peer and transport plugin. Check that this could be a valid
1971 * address. If so, consider adding it to the list
1974 * @param cls closure
1975 * @param addr pointer to the address
1976 * @param addrlen length of addr
1977 * @return GNUNET_OK if this is a plausible address for this peer
1982 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1984 //struct Plugin *plugin = cls;
1986 /* check if the address is plausible; if so,
1987 add it to our list! */
1989 GNUNET_assert(cls !=NULL);
1990 //FIXME mitm is not checked
1991 //Mac Address has 6 bytes
1994 /* TODO check for bad addresses like multicast, broadcast, etc */
1999 return GNUNET_SYSERR;
2002 return GNUNET_SYSERR;
2006 * Function called for a quick conversion of the binary address to
2007 * a numeric address. Note that the caller must not free the
2008 * address and that the next call to this function is allowed
2009 * to override the address again.
2011 * @param cls closure
2012 * @param addr binary address
2013 * @param addrlen length of the address
2014 * @return string representing the same address
2017 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
2019 static char ret[40];
2020 const unsigned char * input;
2022 //GNUNET_assert(cls !=NULL);
2025 /* invalid address (MAC addresses have 6 bytes) */
2029 input = (const unsigned char*) addr;
2030 GNUNET_snprintf(ret, sizeof(ret),
2031 "%s Mac-Address %02X:%02X:%02X:%02X:%02X:%02X", PROTOCOL_PREFIX,
2032 input[0], input[1], input[2], input[3], input[4], input[5]);
2037 * function to check if bitfield is representation of fragments of the message
2038 * @param rec_message message to check
2042 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
2044 uint64_t checkfragments = 0;
2045 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2047 while (rec_queue != NULL)
2049 setBit((char*) &checkfragments, rec_queue->num);
2050 rec_queue = rec_queue->next;
2053 GNUNET_assert(checkfragments == rec_message->received_fragments);
2057 * Function to test if fragment number already exists in the fragments received
2059 * @param rec_message message this fragment belongs to
2060 * @param fh Fragmentheader of the fragment
2061 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2065 is_double_msg(struct Receive_Message_Queue * rec_message,
2066 struct FragmentationHeader * fh)
2068 //test if bitfield is okay
2070 check_message_fragment_bitfield(rec_message);
2073 return testBit((char *) &rec_message->received_fragments, ntohs(
2074 fh->fragment_off_or_num));
2079 * Function to insert a fragment in a queue of a message
2080 * @param session session the fragment belongs to
2081 * @param rec_queue fragment to add
2085 insert_fragment_in_queue(struct Receive_Message_Queue * rec_message,
2086 struct Receive_Fragment_Queue * rec_queue)
2088 struct Receive_Fragment_Queue * rec_queue2 = rec_message->frag_head;
2089 struct WlanHeader * wlanheader = NULL;
2091 GNUNET_assert(rec_message != NULL);
2092 GNUNET_assert(rec_queue != NULL);
2094 //this is the first fragment of the message (fragment id 0)
2095 if (rec_queue->num == 0)
2097 wlanheader = (struct WlanHeader *) rec_queue->msg;
2098 rec_message->rec_size = ntohs(wlanheader->header.size);
2102 while (rec_queue2 != NULL)
2104 if (rec_queue2->num > rec_queue->num)
2106 //next element number is grater than the current num
2107 GNUNET_CONTAINER_DLL_insert_before(rec_message->frag_head, rec_message->frag_tail, rec_queue2, rec_queue);
2108 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2111 rec_queue = rec_queue->next;
2113 //no element has a grater number
2114 GNUNET_CONTAINER_DLL_insert_tail(rec_message->frag_head, rec_message->frag_tail, rec_queue);
2116 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2120 * Function to dispose the fragments received for a message and the message
2121 * @param plugin pointer to the plugin struct
2122 * @param rec_message pointer to the struct holding the message which should be freed
2126 free_receive_message(struct Plugin* plugin,
2127 struct Receive_Message_Queue * rec_message)
2129 GNUNET_assert(rec_message !=NULL);
2130 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2131 struct Receive_Fragment_Queue * rec_queue2;
2133 while (rec_queue != NULL)
2135 rec_queue2 = rec_queue;
2136 rec_queue = rec_queue->next;
2137 GNUNET_free(rec_queue2);
2140 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rec_message);
2142 GNUNET_assert(plugin->pending_receive_messages > 0);
2143 GNUNET_assert(rec_message->session->fragment_messages_in_count > 0);
2145 plugin->pending_receive_messages--;
2146 rec_message->session->fragment_messages_in_count--;
2147 GNUNET_free(rec_message);
2151 * Function to check if all fragments of a message have been received
2152 * @param plugin the plugin handle
2153 * @param session_light information of the message sender
2154 * @param session session the message belongs to
2155 * @param rec_message pointer to the message that should be checked
2159 check_rec_finished_msg(struct Plugin* plugin,
2160 struct Session_light * session_light, struct Session * session,
2161 struct Receive_Message_Queue * rec_message)
2163 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2164 int packetsize = rec_message->rec_size;
2167 uint64_t bitfield = 0;
2170 GNUNET_assert(rec_message !=NULL);
2171 //check if first fragment is present
2172 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2177 check_message_fragment_bitfield(rec_message);
2180 bitfield = ~bitfield;
2181 bitfield = bitfield >> (63 - rec_message->frag_tail->num);
2182 if (rec_message->received_fragments == bitfield)
2185 while (rec_queue != NULL)
2187 sum += rec_queue->size;
2188 rec_queue = rec_queue->next;
2190 //sum should always be smaller or equal of
2191 GNUNET_assert(sum <= packetsize);
2192 if (sum == packetsize)
2196 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2197 "check_rec_finished_msg: A message for %p is complete\n", session);
2201 //copy fragments together
2202 msg = GNUNET_malloc(packetsize);
2203 rec_queue = rec_message->frag_head;
2205 while (rec_queue != NULL)
2207 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2208 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
2209 aktnum += rec_queue->size;
2210 rec_queue = rec_queue->next;
2212 free_receive_message(plugin, rec_message);
2213 //call wlan_process_helper to process the message
2214 wlan_data_massage_handler(plugin, session_light,
2215 (struct GNUNET_MessageHeader*) msg);
2216 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2224 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2227 GNUNET_assert(client != NULL);
2228 GNUNET_assert(cls != NULL);
2229 struct Session * session = (struct Session *) client;
2230 struct Plugin * plugin = (struct Plugin *) cls;
2232 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2233 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2234 distance[0].value = htonl(1);
2235 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2236 distance[1].value = htonl(0);
2239 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2240 "Calling plugin->env->receive for session %p; %s\n", session,
2241 wlan_plugin_address_to_string(NULL, session->addr, 6));
2244 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2245 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2246 session->addr, sizeof(session->addr));
2250 * handels the data after all fragments are put together
2252 * @param session_light
2253 * @param hdr pointer to the data
2256 wlan_data_massage_handler(struct Plugin * plugin,
2257 struct Session_light * session_light,
2258 const struct GNUNET_MessageHeader * hdr)
2260 struct WlanHeader * wlanheader = NULL;
2261 struct Session * session = NULL;
2262 const char * tempmsg = NULL;
2263 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2264 struct GNUNET_PeerIdentity tmptarget;
2266 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2271 GNUNET_ERROR_TYPE_DEBUG,
2272 "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2276 GNUNET_assert(session_light != NULL);
2277 if (session_light->session == NULL)
2279 session_light->session = search_session(plugin, session_light->addr);
2281 session = session_light->session;
2282 wlanheader = (struct WlanHeader *) hdr;
2283 tempmsg = (char*) &wlanheader[1];
2284 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2286 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2289 //wrong crc, dispose message
2290 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2291 "Wlan message Header crc was wrong\n");
2295 //if not in session list
2296 if (session == NULL)
2300 GNUNET_ERROR_TYPE_DEBUG,
2301 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2302 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2303 sizeof(struct WlanHeader));
2305 //try if it is a hello message
2306 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2307 + sizeof(struct WlanHeader))
2309 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2311 if (GNUNET_HELLO_get_id(
2312 (const struct GNUNET_HELLO_Message *) temp_hdr,
2313 &tmptarget) == GNUNET_OK)
2315 session = create_session(plugin, session_light->addr);
2316 session_light->session = session;
2317 memcpy(&session->target, &tmptarget,
2318 sizeof(struct GNUNET_PeerIdentity));
2322 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2323 "WLAN client not in session list and hello message not okay\n");
2330 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2331 "WLAN client not in session list and not a hello message\n");
2338 GNUNET_ERROR_TYPE_WARNING,
2339 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2340 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2341 sizeof(struct WlanHeader));
2346 //"receive" the message
2349 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2350 (const char *) temp_hdr,
2351 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2357 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2358 "wlan_data_massage_handler got wrong message type\n");
2364 * function to add an ack to send it for a received fragment
2365 * @param plugin pointer to the global plugin structure
2366 * @param session pointer to the session this ack belongs to
2367 * @param bitfield bitfield to send
2368 * @param fh pointer to the fragmentation header which we would like to acknolage
2372 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2373 uint64_t bitfield, struct FragmentationHeader * fh)
2375 struct AckSendQueue * ack;
2377 GNUNET_assert(plugin != NULL);
2378 GNUNET_assert(session != NULL);
2379 GNUNET_assert(fh != NULL);
2381 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2382 ack->fragments_field = bitfield;
2383 ack->message_id = ntohl(fh->message_id);
2384 ack->session = session;
2386 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2387 plugin->ack_send_queue_tail, ack);
2392 * function to get the receive message from the message id and the session
2393 * @param plugin pointer to the plugin struct
2394 * @param session session this fragment belongs to
2395 * @param message_id id of the message
2398 struct Receive_Message_Queue *
2399 get_receive_message(struct Plugin * plugin, struct Session * session,
2400 uint32_t message_id)
2402 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2403 while (rec_message != NULL)
2405 if ((rec_message->message_id_in == message_id) && (rec_message->session
2410 rec_message = rec_message->next;
2416 * function to get the receive message of a session
2417 * @param plugin pointer to the plugin struct
2418 * @param session session this fragment belongs to
2421 struct Receive_Message_Queue *
2422 get_receive_message_from_session(struct Plugin * plugin,
2423 struct Session * session)
2425 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2426 while (rec_message != NULL)
2428 if (rec_message->session == session)
2432 rec_message = rec_message->next;
2438 * function to insert a received fragment into the right fragment queue of the right message
2439 * @param plugin pointer to the plugin struct
2440 * @param session_light pointer to the session_light struct of this message
2441 * @param session session this fragment belongs to
2442 * @param fh pointer to the header of the fragment
2443 * @return new fragment bitfield for the message
2447 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2448 struct Session_light * session_light, struct Session * session,
2449 struct FragmentationHeader * fh)
2451 struct Receive_Fragment_Queue * rec_queue = NULL;
2452 struct Receive_Message_Queue * rec_message;
2453 const char * tempmsg = (char*) &fh[1];
2454 uint64_t retval = 0;
2456 //TODO fragments do not timeout
2457 //check if message_id is right or it is a new msg
2458 GNUNET_assert(fh != NULL);
2460 rec_message = get_receive_message(plugin, session, ntohs(fh->message_id));
2462 if (rec_message == NULL)
2464 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2467 //new message incoming
2468 rec_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2469 rec_message->message_id_in = ntohs(fh->message_id);
2470 rec_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2471 rec_message->session = session;
2472 rec_message->timeout = GNUNET_TIME_absolute_add(
2473 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2474 rec_message->received_fragments = 0;
2476 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rec_message);
2478 session->fragment_messages_in_count++;
2479 plugin->pending_receive_messages++;
2483 GNUNET_ERROR_TYPE_DEBUG,
2484 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2485 rec_message->message_id_in, session->fragment_messages_in_count,
2486 plugin->pending_receive_messages);
2493 GNUNET_ERROR_TYPE_INFO,
2494 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2495 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2500 if (is_double_msg(rec_message, fh) != GNUNET_YES)
2504 rec_queue = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2505 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2506 rec_queue->size = ntohs(fh->header.size)
2507 - sizeof(struct FragmentationHeader);
2508 rec_queue->num = ntohs(fh->fragment_off_or_num);
2509 rec_queue->msg = (char*) &(rec_queue[1]);
2510 //copy msg to buffer
2511 memcpy((char *) rec_queue->msg, tempmsg, rec_queue->size);
2512 insert_fragment_in_queue(rec_message, rec_queue);
2514 retval = rec_message->received_fragments;
2518 GNUNET_ERROR_TYPE_DEBUG,
2519 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2520 rec_message->rec_size, rec_queue->size,
2521 rec_message->received_fragments, rec_message->message_id_in, session);
2524 check_rec_finished_msg(plugin, session_light, session, rec_message);
2528 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2529 retval = rec_message->received_fragments;
2537 * Function used for to process the data received from the wlan interface
2539 * @param cls the plugin handle
2540 * @param session_light FIXME: document
2541 * @param hdr hdr of the GNUNET_MessageHeader
2544 wlan_data_helper(void *cls, struct Session_light * session_light,
2545 const struct GNUNET_MessageHeader * hdr)
2547 struct Plugin *plugin = cls;
2548 struct Session * session = NULL;
2550 struct FragmentationHeader * fh = NULL;
2551 struct FragmentationAckHeader * fah = NULL;
2552 struct FragmentMessage * fm = NULL;
2554 const char * tempmsg = NULL;
2556 uint64_t fragment_bitfield = 0;
2559 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2562 //TODO better DOS protection, error handling
2563 //TODO test first than create session
2564 GNUNET_assert(session_light != NULL);
2568 GNUNET_ERROR_TYPE_DEBUG,
2569 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2570 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2571 session_light->addr, 6));
2574 if (session_light->session == NULL)
2576 session_light->session = get_Session(plugin, session_light->addr);
2578 GNUNET_assert(GNUNET_HELLO_get_id(
2579 (const struct GNUNET_HELLO_Message *) &hdr[1],
2580 &(session_light->session->target) ) != GNUNET_SYSERR);
2585 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2588 GNUNET_assert(session_light != NULL);
2589 if (session_light->session == NULL)
2591 session_light->session = search_session(plugin, session_light->addr);
2593 session = session_light->session;
2595 fh = (struct FragmentationHeader *) hdr;
2596 tempmsg = (char*) &fh[1];
2600 GNUNET_ERROR_TYPE_DEBUG,
2601 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2602 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2603 hdr->size), wlan_plugin_address_to_string(NULL,
2604 session_light->addr, 6));
2607 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2609 //wrong crc, dispose message
2610 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2614 //if in the session list
2615 if (session != NULL)
2617 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2618 session_light, session, fh);
2624 GNUNET_ERROR_TYPE_INFO,
2625 "WLAN client not in session list, fragment num %u, message id %u\n",
2626 ntohs(fh->fragment_off_or_num), ntohs(fh->message_id));
2627 wlan_data_massage_handler(plugin, session_light,
2628 (struct GNUNET_MessageHeader *) tempmsg);
2629 session = session_light->session;
2630 //test if a session was created
2631 if (session == NULL)
2635 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2638 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2639 check_next_fragment_timeout(plugin);
2644 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2649 GNUNET_ERROR_TYPE_DEBUG,
2650 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2651 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2652 session_light->addr, 6));
2655 GNUNET_assert(session_light != NULL);
2656 if (session_light->session == NULL)
2658 session_light->session = search_session(plugin, session_light->addr);
2659 GNUNET_assert(session_light->session != NULL);
2661 session = session_light->session;
2662 fah = (struct FragmentationAckHeader *) hdr;
2663 fm = get_fragment_message_from_session_and_id(session, ntohl(
2668 fm->ack_bitfield = fm->ack_bitfield | ntohll(fah->fragment_field);
2669 check_finished_fragment(plugin, fm);
2673 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2674 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2683 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2684 "WLAN packet inside the WLAN helper packet has not the right type\n");
2689 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2690 "Helper finished\n");
2696 macprinter(u_int8_t * mac)
2698 static char macstr[20];
2699 sprintf(macstr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac[0], mac[1], mac[2],
2700 mac[3], mac[4], mac[5]);
2705 * Function used for to process the data from the suid process
2707 * @param cls the plugin handle
2708 * @param client client that send the data (not used)
2709 * @param hdr header of the GNUNET_MessageHeader
2713 wlan_process_helper(void *cls, void *client,
2714 const struct GNUNET_MessageHeader *hdr)
2716 struct Plugin *plugin = cls;
2717 struct ieee80211_frame * wlanIeeeHeader = NULL;
2718 struct Session_light * session_light = NULL;
2719 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2724 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
2728 GNUNET_ERROR_TYPE_DEBUG,
2729 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2733 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2734 GNUNET_assert(ntohs(hdr->size) >= sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader));
2735 wlanIeeeHeader = (struct ieee80211_frame *) &hdr[1];
2737 //process only if it is an broadcast or for this computer both with the gnunet bssid
2740 if (memcmp(&(wlanIeeeHeader->i_addr3), mac_bssid,
2741 sizeof(struct MacAddress)) == 0)
2743 //check for broadcast or mac
2744 if (memcmp(&(wlanIeeeHeader->i_addr1), bc_all_mac,
2745 sizeof(struct MacAddress) == 0) || memcmp(
2746 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2747 sizeof(struct MacAddress)) == 0)
2750 // process the inner data
2753 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2754 - sizeof(struct GNUNET_MessageHeader);
2756 session_light = GNUNET_malloc(sizeof(struct Session_light));
2757 memcpy(session_light->addr, &(wlanIeeeHeader->i_addr2),
2758 sizeof(struct MacAddress));
2759 //session_light->session = search_session(plugin,session_light->addr);
2762 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2763 while (pos < datasize)
2765 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2768 wlan_data_helper(plugin, session_light, temp_hdr);
2769 pos += ntohs(temp_hdr->size);
2774 GNUNET_free(session_light);
2779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2780 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2781 wlanIeeeHeader->i_addr1));
2788 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2789 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2790 wlanIeeeHeader->i_addr2));
2796 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
2801 GNUNET_ERROR_TYPE_DEBUG,
2802 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %u\n",
2806 //TODO more control messages
2807 //TODO use struct wlan_helper_control
2808 if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
2810 //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
2811 memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
2812 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2813 "Notifying transport of address %s\n",
2814 wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(
2815 hdr->size) - sizeof(struct GNUNET_MessageHeader)));
2816 plugin->env->notify_address(plugin->env->cls, "wlan",
2817 &plugin->mac_address.mac, sizeof(struct MacAddress),
2818 GNUNET_TIME_UNIT_FOREVER_REL);
2822 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
2823 macprinter(plugin->mac_address.mac));
2831 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2832 "WLAN helper packet has not the right type\n");
2838 * We have been notified that wlan-helper has written something to stdout.
2839 * Handle the output, then reschedule this function to be called again once
2840 * more is available.
2842 * @param cls the plugin handle
2843 * @param tc the scheduling context
2847 wlan_plugin_helper_read(void *cls,
2848 const struct GNUNET_SCHEDULER_TaskContext *tc)
2850 struct Plugin *plugin = cls;
2851 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2856 "Start reading from STDIN\n");
2859 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2862 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2865 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2870 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2871 _("Finished reading from wlan-helper stdout with code: %d\n"),
2876 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2877 GNUNET_NO, GNUNET_NO);
2879 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2880 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2881 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2882 &wlan_plugin_helper_read, plugin);
2886 * Start the gnunet-wlan-helper process.
2888 * @param plugin the transport plugin
2889 * @param testmode should we use the dummy driver for testing?
2890 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2893 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2895 const char * filename = "gnunet-transport-wlan-helper";
2896 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2897 if (plugin->server_stdout == NULL)
2898 return GNUNET_SYSERR;
2900 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2901 if (plugin->server_stdin == NULL)
2902 return GNUNET_SYSERR;
2905 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2906 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2907 plugin->interface, testmode);
2909 /* Start the server process */
2911 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2912 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2913 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2914 if (plugin->server_proc == NULL)
2917 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2918 "Failed to start gnunet-wlan-helper process\n");
2920 return GNUNET_SYSERR;
2923 /* Close the write end of the read pipe */
2924 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2926 /* Close the read end of the write pipe */
2927 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2929 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2930 GNUNET_DISK_PIPE_END_READ);
2931 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2932 GNUNET_DISK_PIPE_END_WRITE);
2934 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2937 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2938 "Adding server_read_task for the wlan-helper\n");
2943 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2944 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2945 &wlan_plugin_helper_read, plugin);
2951 * Exit point from the plugin.
2952 * @param cls pointer to the api struct
2957 libgnunet_plugin_transport_wlan_done(void *cls)
2959 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2960 struct Plugin *plugin = api->cls;
2963 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2964 "libgnunet_plugin_transport_wlan_done started\n");
2967 GNUNET_assert(cls !=NULL);
2969 if (plugin->suid_tokenizer != NULL)
2970 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2972 if (plugin->data_tokenizer != NULL)
2973 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
2975 GNUNET_free_non_null(plugin->interface);
2976 GNUNET_free (plugin);
2982 * Entry point for the plugin.
2984 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2985 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2988 libgnunet_plugin_transport_wlan_init(void *cls)
2990 //struct GNUNET_SERVICE_Context *service;
2991 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2992 struct GNUNET_TRANSPORT_PluginFunctions *api;
2993 struct Plugin *plugin;
2994 static unsigned long long testmode = 0;
2996 GNUNET_assert(cls !=NULL);
2998 plugin = GNUNET_malloc (sizeof (struct Plugin));
3000 plugin->pendingsessions = 0;
3001 plugin->session_count = 0;
3002 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3003 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3004 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3006 set_next_beacon_time(plugin);
3008 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3010 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3011 "transport-wlan", "TESTMODE", &testmode))
3015 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3017 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3018 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3020 libgnunet_plugin_transport_wlan_done(plugin);
3025 wlan_transport_start_wlan_helper(plugin, testmode);
3026 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3029 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3031 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3032 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3034 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3036 api->send = &wlan_plugin_send;
3037 api->disconnect = &wlan_plugin_disconnect;
3038 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3039 api->check_address = &wlan_plugin_address_suggested;
3040 api->address_to_string = &wlan_plugin_address_to_string;
3042 start_next_message_id();
3045 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3051 /* end of plugin_transport_wlan.c */