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"
38 //#include <netinet/ip.h>
42 #define PROTOCOL_PREFIX "wlan"
45 * Max size of packet from helper
50 * Time until retransmission of a fragment in ms
52 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
55 * max size of fragment queue
57 #define FRAGMENT_QUEUE_SIZE 10
59 * max messages in fragment queue per session/client
61 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
64 * time until message in in queue
66 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
69 * max messages in in queue
71 #define MESSAGES_IN_QUEUE_SIZE 10
73 * max messages in in queue per session/client
75 #define MESSAGES_IN_QUEUE_PER_SESSION 1
77 * scaling factor for hello beacon
79 #define HALLO_BEACON_SCALING_FACTOR 900
81 #define DEBUG_wlan GNUNET_NO
82 #define DEBUG_wlan_retransmission GNUNET_NO
83 #define DEBUG_wlan_ip_udp_packets_on_air GNUNET_NO
85 #define MESSAGE_LENGHT_UNKNOWN -1
86 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
88 * size of log for recently used incomming messages id
90 #define MESSAGE_ID_BACKLOG_SIZE 5
92 * After how long do we expire an address that we
93 * learned from another peer if it is not reconfirmed
96 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
98 #define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
100 #define IEEE80211_FC0_VERSION_MASK 0x03
101 #define IEEE80211_FC0_VERSION_SHIFT 0
102 #define IEEE80211_FC0_VERSION_0 0x00
103 #define IEEE80211_FC0_TYPE_MASK 0x0c
104 #define IEEE80211_FC0_TYPE_SHIFT 2
105 #define IEEE80211_FC0_TYPE_MGT 0x00
106 #define IEEE80211_FC0_TYPE_CTL 0x04
107 #define IEEE80211_FC0_TYPE_DATA 0x08
110 * Structure of an internet header, naked of options.
114 #if __BYTE_ORDER == __LITTLE_ENDIAN
115 unsigned int ip_hl:4; /* header length */
116 unsigned int ip_v:4; /* version */
118 #if __BYTE_ORDER == __BIG_ENDIAN
119 unsigned int ip_v:4; /* version */
120 unsigned int ip_hl:4; /* header length */
122 u_int8_t ip_tos; /* type of service */
123 u_short ip_len; /* total length */
124 u_short ip_id; /* identification */
125 u_short ip_off; /* fragment offset field */
126 #define IP_RF 0x8000 /* reserved fragment flag */
127 #define IP_DF 0x4000 /* dont fragment flag */
128 #define IP_MF 0x2000 /* more fragments flag */
129 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
130 u_int8_t ip_ttl; /* time to live */
131 u_int8_t ip_p; /* protocol */
132 u_short ip_sum; /* checksum */
133 struct in_addr ip_src, ip_dst; /* source and dest address */
145 * generic definitions for IEEE 802.11 frames
147 struct ieee80211_frame {
150 u_int8_t i_addr1[IEEE80211_ADDR_LEN];
151 u_int8_t i_addr2[IEEE80211_ADDR_LEN];
152 u_int8_t i_addr3[IEEE80211_ADDR_LEN];
154 #if DEBUG_wlan_ip_udp_packets_on_air
161 * Initial handshake message for a session.
163 struct WelcomeMessage
166 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
168 struct GNUNET_MessageHeader header;
171 * Identit*mac_y of the node connecting (TCP client)
173 struct GNUNET_PeerIdentity clientIdentity;
178 * Encapsulation of all of the state of the plugin.
185 struct GNUNET_TRANSPORT_PluginEnvironment *env;
188 * List of open sessions. head
190 struct Sessionqueue *sessions;
193 * List of open sessions. tail
195 struct Sessionqueue *sessions_tail;
200 unsigned int session_count;
203 * encapsulation of data from the local wlan helper program
205 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
208 * encapsulation of packets received from the wlan helper
210 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
212 * encapsulation of packets received
214 struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
217 * stdout pipe handle for the gnunet-wlan-helper process
219 struct GNUNET_DISK_PipeHandle *server_stdout;
222 * stdout file handle for the gnunet-wlan-helper process
224 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
227 * stdin pipe handle for the gnunet-wlan-helper process
229 struct GNUNET_DISK_PipeHandle *server_stdin;
232 * stdin file handle for the gnunet-wlan-helper process
234 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
237 * ID of the gnunet-wlan-server std read task
239 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
242 * ID of the gnunet-wlan-server std read task
244 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
247 * ID of the delay task for writing
249 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
252 * The process id of the wlan process
254 struct GNUNET_OS_Process *server_proc;
257 * The interface of the wlan card given to us by the user.
262 * The mac_address of the wlan card given to us by the helper.
264 struct MacAddress mac_address;
267 * Sessions currently pending for transmission
268 * to this peer, if any.
270 struct Sessionqueue * pending_Sessions_head;
273 * Sessions currently pending for transmission
274 * to this peer (tail), if any.
276 struct Sessionqueue * pending_Sessions_tail;
279 * number of pending sessions
281 unsigned int pendingsessions;
284 * Messages in the fragmentation queue, head
286 struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
289 * Messages in the in Queue, head
291 struct Receive_Message_Queue * receive_messages_head;
294 * Messages in the in Queue, tail
296 struct Receive_Message_Queue * receive_messages_teil;
299 * number of messages in the in queue
301 unsigned int pending_receive_messages;
304 * time of the next "hello-beacon"
306 struct GNUNET_TIME_Absolute beacon_time;
309 * queue to send acks for received fragments (head)
311 struct AckSendQueue * ack_send_queue_head;
314 * queue to send acks for received fragments (tail)
316 struct AckSendQueue * ack_send_queue_tail;
320 * Struct to store data if file write did not accept the whole packet
324 struct Plugin * plugin;
326 struct GNUNET_MessageHeader * msgstart;
331 * Queue of sessions, for the general session queue and the pending session queue
336 struct Sessionqueue * next;
337 struct Sessionqueue * prev;
338 struct Session * content;
342 * Queue for the fragments received
345 struct Receive_Fragment_Queue
347 struct Receive_Fragment_Queue * next;
348 struct Receive_Fragment_Queue * prev;
352 struct Radiotap_rx rxinfo;
356 struct Session_id_fragment_triple
358 struct Session * session;
360 struct FragmentMessage * fm;
364 struct Plugin_Session_pair
366 struct Plugin * plugin;
367 struct Session * session;
371 * Queue for the fragments received
373 struct Receive_Message_Queue
375 struct Receive_Message_Queue * next;
377 struct Receive_Message_Queue * prev;
380 * current number for message incoming, to distinguish between the messages
382 uint32_t message_id_in;
385 * size of the message received,
386 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
387 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
392 * Sorted queue with the fragments received; head
395 struct Receive_Fragment_Queue * frag_head;
398 * Sorted queue with the fragments received; tail
401 struct Receive_Fragment_Queue * frag_tail;
404 * Session this fragment belongs to
407 struct Session * session;
410 * Timeout value for the pending message.
412 struct GNUNET_TIME_Absolute timeout;
415 * Bitfield of received fragments
418 uint64_t received_fragments;
422 * Information kept for each message that is yet to
425 struct PendingMessage
429 * The pending message
434 * Size of the message
439 * Continuation function to call once the message
440 * has been sent. Can be NULL if there is no
441 * continuation to call.
443 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
446 * Cls for transmit_cont
448 void * transmit_cont_cls;
451 * Timeout value for the pending message.
453 struct GNUNET_TIME_Absolute timeout;
458 * Queue for acks to send for fragments recived
464 * next ack in the ack send queue
466 struct AckSendQueue * next;
468 * previous ack in the ack send queue
470 struct AckSendQueue * prev;
472 * pointer to the session this ack belongs to
474 struct Session * session;
476 * ID of message, to distinguish between the messages, picked randomly.
481 * Bit field for received fragments
483 uint64_t fragments_field;
488 * Session infos gathered from a messages
494 * the session this message belongs to
496 struct Session * session;
500 struct MacAddress addr;
504 * Session handle for connections.
512 struct SessionHeader header;
515 * Pointer to the global plugin struct.
517 struct Plugin *plugin;
520 * Message currently pending for transmission
521 * to this peer, if any.
523 struct PendingMessage *pending_message;
526 * Message currently pending for transmission
527 * to this peer, if any.
529 struct PendingMessage *pending_message2;
532 * To whom are we talking to (set to our identity
533 * if we are still waiting for the welcome message)
535 struct GNUNET_PeerIdentity target;
540 struct MacAddress addr;
543 * Address of the other peer (either based on our 'connect'
544 * call or on our 'accept' call).
549 * Last activity on this connection. Used to select preferred
552 struct GNUNET_TIME_Absolute last_activity;
555 * count of messages in the fragment out queue for this session
558 int fragment_messages_out_count;
561 * count of messages in the fragment in queue for this session
564 int fragment_messages_in_count;
573 * backlog for incoming message ids
575 uint32_t message_id_backlog[MESSAGE_ID_BACKLOG_SIZE];
577 * position in the backlog
579 int message_id_backlog_pos;
583 * Struct for Messages in the fragment queue
586 struct FragmentMessage
589 * heap pointer of this message
591 struct GNUNET_CONTAINER_HeapNode * node;
594 * Session this message belongs to
597 struct Session *session;
600 * This is a doubly-linked list.
602 struct FragmentMessage *next;
605 * This is a doubly-linked list.
607 struct FragmentMessage *prev;
610 * The pending message
615 * 0 if not in ack queue
622 * Timeout value for the pending message.
624 struct GNUNET_TIME_Absolute timeout;
627 * Timeout value for the pending fragments.
628 * Stores the time when the next msg fragment ack has to be received
630 struct GNUNET_TIME_Absolute next_ack;
633 * bitfield with all acks received for this message
635 uint64_t ack_bitfield;
638 * Size of the message
643 * pos / next fragment number in the message, for fragmentation/segmentation,
644 * some acks can be missing but there is still time
646 uint32_t message_pos;
649 * current number for message outgoing, to distinguish between the messages
651 uint32_t message_id_out;
655 * Header for messages which need fragmentation
657 struct FragmentationAckHeader
660 struct GNUNET_MessageHeader header;
663 * ID of message, to distinguish between the messages, picked randomly.
665 uint32_t message_id GNUNET_PACKED;
668 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
670 uint64_t fragment_field GNUNET_PACKED;
675 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
678 * Generates a nice hexdump of a memory area.
680 * \param mem pointer to memory to dump
681 * \param length how many bytes to dump
683 void hexdump(void *mem, unsigned length)
686 char *src = (char*)mem;
689 "dumping %u bytes from %p\r\n"
690 " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\r\n"
696 for (i=0; i<length; i+=16, src+=16) {
699 t += sprintf(t, "%04x: ", i);
700 for ( j=0; j<16; j++) {
702 t += sprintf(t, "%02X", src[j] & 0xff);
704 t += sprintf(t, " ");
705 t += sprintf(t, j%2 ? " " : "-");
708 t += sprintf(t, " ");
709 for (j=0; j<16; j++) {
711 if (isprint((unsigned char)src[j]))
712 t += sprintf(t, "%c", src[j]);
714 t += sprintf(t, ".");
716 t += sprintf(t, " ");
720 t += sprintf(t, "\r\n");
726 * Sets a bit active in the bitArray. Increment bit-specific
727 * usage counter on disk only if below 4bit max (==15).
729 * @param bitArray memory area to set the bit in
730 * @param bitIdx which bit to set
733 setBit(char *bitArray, unsigned int bitIdx)
736 unsigned int targetBit;
738 arraySlot = bitIdx / 8;
739 targetBit = (1L << (bitIdx % 8));
740 bitArray[arraySlot] |= targetBit;
744 * Checks if a bit is active in the bitArray
746 * @param bitArray memory area to set the bit in
747 * @param bitIdx which bit to test
748 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
751 testBit(char *bitArray, unsigned int bitIdx)
754 unsigned int targetBit;
757 targetBit = (1L << (bitIdx % 8));
758 if (bitArray[slot] & targetBit)
764 * get the next message number, at the moment just a random one
765 * @return returns the next valid message-number for sending packets
768 get_next_message_id()
770 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
774 * search for a session with the addr
776 * @param plugin pointer to the plugin struct
777 * @param addr pointer to the mac address of the peer
778 * @return returns the session
780 static struct Session *
781 search_session(struct Plugin *plugin, const struct MacAddress *addr)
783 struct Sessionqueue * queue = plugin->sessions;
785 while (queue != NULL)
787 GNUNET_assert (queue->content != NULL);
788 if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
789 return queue->content; /* session found */
796 * Function called for a quick conversion of the binary address to
797 * a numeric address. Note that the caller must not free the
798 * address and that the next call to this function is allowed
799 * to override the address again.
802 * @param addr binary address
803 * @param addrlen length of the address
804 * @return string representing the same address
807 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
810 const struct MacAddress *mac;
812 if (addrlen != sizeof(struct MacAddress))
818 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
819 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
820 mac->mac[4], mac->mac[5]);
825 * create a new session
827 * @param plugin pointer to the plugin struct
828 * @param addr pointer to the mac address of the peer
829 * @return returns the session
832 static struct Session *
833 create_session(struct Plugin *plugin, const struct MacAddress * addr)
835 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
837 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
839 queue->content = GNUNET_malloc (sizeof (struct Session));
840 queue->content->plugin = plugin;
841 queue->content->addr = *addr;
842 queue->content->fragment_messages_out_count = 0;
843 queue->content->fragment_messages_in_count = 0;
844 queue->content->message_id_backlog_pos = 0;
846 plugin->session_count++;
849 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
850 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
853 return queue->content;
857 * Get session from address, create if no session exists
859 * @param plugin pointer to the plugin struct
860 * @param addr pointer to the mac address of the peer
861 * @return returns the session
863 static struct Session *
864 get_session(struct Plugin *plugin, const struct MacAddress *addr)
866 struct Session * session = search_session(plugin, addr);
869 return create_session(plugin, addr);
873 * Queue the session to send data
874 * checks if there is a message pending
875 * checks if this session is not allready in the queue
876 * @param plugin pointer to the plugin
877 * @param session pointer to the session to add
880 queue_session(struct Plugin *plugin, struct Session * session)
882 struct Sessionqueue * queue = plugin->pending_Sessions_head;
884 if (session->pending_message != NULL)
886 while (queue != NULL)
888 // content is never NULL
889 GNUNET_assert (queue->content != NULL);
890 // is session already in queue?
891 if (session == queue->content)
899 // Session is not in the queue
901 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
902 queue->content = session;
905 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
906 plugin->pending_Sessions_tail, queue);
907 plugin->pendingsessions++;
913 * Function to schedule the write task, executed after a delay
914 * @param cls pointer to the plugin struct
915 * @param tc GNUNET_SCHEDULER_TaskContext pointer
918 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
920 struct Plugin * plugin = cls;
921 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
923 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
926 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
927 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
929 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
930 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
931 &do_transmit, plugin);
936 * Function to calculate the time of the next periodic "hello-beacon"
937 * @param plugin pointer to the plugin struct
941 set_next_beacon_time(struct Plugin * const plugin)
943 //under 10 known peers: once a second
944 if (plugin->session_count < 10)
946 plugin->beacon_time = GNUNET_TIME_absolute_add(
947 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
948 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
950 //under 30 known peers: every 10 seconds
951 else if (plugin->session_count < 30)
953 plugin->beacon_time = GNUNET_TIME_absolute_add(
954 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
955 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
957 //over 30 known peers: once a minute
960 plugin->beacon_time = GNUNET_TIME_absolute_add(
961 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
962 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
967 * Function to get the timeout value for acks for this session
968 * @param fm pointer to the FragmentMessage to get the next timeout
969 * @return time until the next ack should be received, in GNUNET_TIME_Relative
971 static struct GNUNET_TIME_Relative
972 get_ack_timeout(struct FragmentMessage * fm)
974 return FRAGMENT_TIMEOUT;
978 * Function to set the timer for the next timeout of the fragment queue
979 * @param plugin the handle to the plugin struct
983 set_next_send(struct Plugin * const plugin)
985 struct FragmentMessage * fm;
986 struct GNUNET_TIME_Relative next_send;
987 struct GNUNET_TIME_Absolute next_send_tmp;
990 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
992 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
993 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
996 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
998 //check if some acks are in the queue
999 if (plugin->ack_send_queue_head != NULL)
1001 next_send = GNUNET_TIME_UNIT_ZERO;
1004 //check if there are some fragments in the queue
1007 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
1010 next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
1012 next_send = GNUNET_TIME_relative_min(next_send,
1013 GNUNET_TIME_absolute_get_remaining(next_send_tmp));
1020 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
1021 next_send.rel_value);
1025 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
1027 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1029 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1030 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1031 &do_transmit, plugin);
1036 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1037 &delay_fragment_task, plugin);
1042 * Function to get the next queued Session, removes the session from the queue
1043 * @param plugin pointer to the plugin struct
1044 * @return pointer to the session found, returns NULL if there is now session in the queue
1046 static struct Session *
1047 get_next_queue_session(struct Plugin * plugin)
1049 struct Session * session;
1050 struct Sessionqueue * sessionqueue;
1051 struct Sessionqueue * sessionqueue_alt;
1052 struct PendingMessage * pm;
1053 sessionqueue = plugin->pending_Sessions_head;
1055 while (sessionqueue != NULL)
1057 session = sessionqueue->content;
1059 GNUNET_assert(session != NULL);
1060 pm = session->pending_message;
1065 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1066 "pending message is empty, should not happen. session %p\n",
1071 GNUNET_assert(pm != NULL);
1073 //check for message timeout
1074 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1076 //check if session has no message in the fragment queue
1077 if (session->fragment_messages_out_count
1078 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1080 plugin->pendingsessions--;
1081 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1082 plugin->pending_Sessions_tail, sessionqueue);
1083 GNUNET_free(sessionqueue);
1089 sessionqueue = sessionqueue->next;
1095 session->pending_message = session->pending_message2;
1096 session->pending_message2 = NULL;
1098 //call the cont func that it did not work
1099 if (pm->transmit_cont != NULL)
1100 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1102 GNUNET_free(pm->msg);
1105 if (session->pending_message == NULL)
1107 sessionqueue_alt = sessionqueue;
1108 sessionqueue = sessionqueue->next;
1109 plugin->pendingsessions--;
1110 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1111 plugin->pending_Sessions_tail, sessionqueue_alt);
1113 GNUNET_free(sessionqueue_alt);
1123 * frees the space of a message in the fragment queue (send queue)
1124 * @param plugin the plugin struct
1125 * @param fm message to free
1128 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1130 struct Session * session = fm->session;
1134 (session->fragment_messages_out_count)--;
1135 GNUNET_free_non_null(fm->msg);
1136 GNUNET_CONTAINER_heap_remove_node(fm->node);
1139 queue_session(plugin, session);
1141 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1142 "free pending fragment messages, pending messages remaining %u\n",
1143 GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
1149 * Function to check if there is some space in the fragment queue
1150 * inserts a message if space is available
1151 * @param plugin the plugin struct
1155 check_fragment_queue(struct Plugin * plugin)
1157 struct Session * session;
1158 struct FragmentMessage * fm;
1159 struct GNUNET_PeerIdentity pid;
1161 struct PendingMessage * pm;
1163 if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1164 < FRAGMENT_QUEUE_SIZE)
1166 session = get_next_queue_session(plugin);
1167 if (session != NULL)
1169 pm = session->pending_message;
1170 session->pending_message = NULL;
1171 session->fragment_messages_out_count++;
1172 GNUNET_assert(pm != NULL);
1174 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1175 fm->message_size = pm->message_size;
1177 fm->session = session;
1178 fm->timeout.abs_value = pm->timeout.abs_value;
1179 fm->message_pos = 0;
1180 fm->next_ack = GNUNET_TIME_absolute_get();
1181 fm->message_id_out = get_next_message_id();
1182 fm->ack_bitfield = 0;
1183 fm->node = GNUNET_CONTAINER_heap_insert(
1184 plugin->pending_Fragment_Messages, fm,
1185 GNUNET_TIME_absolute_get().abs_value);
1187 GNUNET_assert(session !=NULL);
1189 if (pm->transmit_cont != NULL)
1191 pid = session->target;
1192 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1194 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1195 "called pm->transmit_cont for %p\n", session);
1201 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1202 "no pm->transmit_cont for %p\n", session);
1207 if (session->pending_message2 != NULL)
1209 session->pending_message = session->pending_message2;
1210 session->pending_message2 = NULL;
1212 queue_session(plugin, session);
1218 //check if timeout changed
1219 set_next_send(plugin);
1223 * Funktion to check if all fragments where send and the acks received
1224 * frees the space if finished
1225 * @param plugin the plugin struct
1226 * @param fm the message to check
1229 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1231 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1232 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1233 - sizeof(struct FragmentationHeader)));
1234 uint64_t tmpfield = UINT64_MAX;
1235 tmpfield = tmpfield >> maxack;
1239 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1240 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1241 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1244 if (fm->ack_bitfield == tmpfield)
1247 #if DEBUG_wlan_retransmission
1248 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1249 "Finished sending and got all acks; message_id %u\n",
1250 fm->message_id_out);
1253 free_fragment_message(plugin, fm);
1255 check_fragment_queue(plugin);
1261 * Function to set the next fragment number
1262 * @param fm use this FragmentMessage
1266 set_next_message_fragment_pos(struct Plugin * plugin,
1267 struct FragmentMessage * fm)
1272 //check if retransmit is needed
1273 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1276 // be positive and try again later :-D
1277 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1278 // find first missing fragment
1280 fm->message_pos = 0;
1282 GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1285 #if DEBUG_wlan_retransmission
1286 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1287 "Retransmit; message_id %u; fragment number %i, size: %u\n",
1288 fm->message_id_out, fm->message_pos, fm->message_size);
1292 //test if ack 0 (or X) was already received
1293 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1302 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1303 struct Radiotap_Send * header)
1306 if (session != NULL)
1308 header->rate = session->rate;
1309 header->tx_power = session->tx_power;
1310 header->antenna = session->antenna;
1315 header->tx_power = 0;
1316 header->antenna = 0;
1323 * function to generate the wlan hardware header for one packet
1324 * @param Header address to write the header to
1325 * @param to_mac_addr address of the recipient
1326 * @param plugin pointer to the plugin struct
1327 * @return GNUNET_YES if there was no error
1330 getWlanHeader(struct ieee80211_frame * Header,
1331 const struct MacAddress * to_mac_addr, struct Plugin * plugin,
1335 const int rate = 11000000;
1337 Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
1338 Header->i_fc[1] = 0x00;
1339 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1340 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1341 memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
1343 tmp16 = (uint16_t*) Header->i_dur;
1344 *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
1346 #if DEBUG_wlan_ip_udp_packets_on_air
1350 Header->ip.ip_dst.s_addr = *((uint32_t*) &to_mac_addr->mac[2]);
1351 Header->ip.ip_src.s_addr = *((uint32_t*) &plugin->mac_address.mac[2]);
1352 Header->ip.ip_v = 4;
1353 Header->ip.ip_hl = 5;
1354 Header->ip.ip_p = 17;
1355 Header->ip.ip_ttl = 1;
1356 Header->ip.ip_len = htons(size + 8);
1357 Header->ip.ip_sum = 0;
1358 x =(uint16_t *) &Header->ip;
1359 count = sizeof(struct iph);
1361 /* This is the inner loop */
1362 crc += (unsigned short) * x++;
1365 /* Add left-over byte, if any */
1367 crc += * (unsigned char *) x;
1368 crc = (crc & 0xffff) + (crc >> 16);
1369 Header->ip.ip_sum = htons(~ (unsigned short) crc);
1372 Header->udp.len = htons(size - sizeof(struct ieee80211_frame));
1382 * @param msgbuf pointer tor the data
1383 * @param msgbuf_size size of the data
1385 * @return 32bit crc value
1389 getcrc32(const char *msgbuf, size_t msgbuf_size)
1392 return GNUNET_CRYPTO_crc32_n(msgbuf, msgbuf_size);;
1398 * @param msgbuf pointer tor the data
1399 * @param msgbuf_size size of the data
1401 * @return 16bit crc value
1405 getcrc16(const char *msgbuf, size_t msgbuf_size)
1407 //TODO calc some crc
1413 send_hello_beacon(struct Plugin * plugin)
1417 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1422 uint16_t hallo_size;
1423 struct GNUNET_MessageHeader * msgheader;
1424 struct ieee80211_frame * ieeewlanheader;
1425 struct Radiotap_Send * radioHeader;
1426 struct GNUNET_MessageHeader * msgheader2;
1428 hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1429 GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1430 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1431 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1434 msgheader = GNUNET_malloc(size);
1435 msgheader->size = htons(size);
1436 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1438 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1439 getRadiotapHeader(plugin, NULL, radioHeader);
1440 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1441 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin, size);
1443 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1444 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1445 + sizeof(struct GNUNET_MessageHeader));
1447 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1448 memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1450 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1452 if (bytes == GNUNET_SYSERR)
1454 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1455 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1456 errno, strerror(errno));
1459 GNUNET_assert(bytes != GNUNET_SYSERR);
1460 GNUNET_assert(bytes == size);
1461 GNUNET_free(msgheader);
1463 set_next_beacon_time(plugin);
1464 set_next_send(plugin);
1469 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1474 struct GNUNET_MessageHeader * msgheader;
1475 struct ieee80211_frame * ieeewlanheader;
1476 struct Radiotap_Send * radioHeader;
1477 struct FragmentationAckHeader * msgheader2;
1479 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1481 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1482 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1485 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1486 "Sending ack for message_id %u with fragment field %u, size %u\n",
1487 ack->message_id, ack->fragments_field, size
1488 - sizeof(struct Radiotap_Send));
1491 msgheader = GNUNET_malloc(size);
1492 msgheader->size = htons(size);
1493 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1495 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1496 getRadiotapHeader(plugin, ack->session, radioHeader);
1497 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1498 getWlanHeader(ieeewlanheader, &ack->session->addr, plugin, size);
1500 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1501 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1502 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1503 msgheader2->message_id = htonl(ack->message_id);
1504 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1506 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1507 if (bytes == GNUNET_SYSERR)
1509 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1510 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1511 errno, strerror(errno));
1514 GNUNET_assert(bytes != GNUNET_SYSERR);
1515 GNUNET_assert(bytes == size);
1516 GNUNET_free(msgheader);
1517 set_next_send(plugin);
1522 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1524 struct Finish_send * finish = cls;
1525 struct Plugin * plugin;
1528 plugin = finish->plugin;
1529 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1531 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1533 GNUNET_free (finish->msgstart);
1534 GNUNET_free (finish);
1537 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1538 finish->msgheader, finish->size);
1539 GNUNET_assert (bytes != GNUNET_SYSERR);
1541 if (bytes != finish->size)
1543 finish->msgheader = finish->msgheader + bytes;
1544 finish->size = finish->size - bytes;
1545 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1546 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1547 &finish_sending, finish);
1551 GNUNET_free(finish->msgstart);
1552 GNUNET_free(finish);
1553 set_next_send(plugin);
1558 * Function called when wlan helper is ready to get some data
1560 * @param cls closure
1561 * @param tc GNUNET_SCHEDULER_TaskContext
1564 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1566 struct Plugin * plugin = cls;
1568 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1569 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1572 struct Session * session;
1573 struct FragmentMessage * fm;
1574 struct ieee80211_frame * ieeewlanheader;
1575 struct Radiotap_Send * radioHeader;
1576 struct GNUNET_MessageHeader * msgheader;
1577 struct FragmentationHeader fragheader;
1578 struct FragmentationHeader * fragheaderptr;
1579 struct Finish_send * finish;
1580 struct AckSendQueue * ack;
1583 const char * copystart;
1587 if (plugin->ack_send_queue_head != NULL)
1589 ack = plugin->ack_send_queue_head;
1590 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1591 plugin->ack_send_queue_tail, ack);
1592 send_ack(plugin, ack);
1597 //test if a "hello-beacon" has to be send
1598 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1600 send_hello_beacon(plugin);
1604 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1608 session = fm->session;
1609 GNUNET_assert(session != NULL);
1611 // test if message timed out
1612 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1615 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1618 free_fragment_message(plugin, fm);
1619 check_fragment_queue(plugin);
1625 //if (fm->message_size > WLAN_MTU)
1627 size = sizeof(struct FragmentationHeader);
1629 set_next_message_fragment_pos(plugin, fm);
1631 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1634 fragheader.fragment_off_or_num = htons(fm->message_pos);
1635 fragheader.message_id = htonl(fm->message_id_out);
1636 copystart = fm->msg + copyoffset;
1637 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1638 WLAN_MTU - sizeof(struct FragmentationHeader));
1642 GNUNET_ERROR_TYPE_DEBUG,
1643 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1644 fm->message_id_out, fm->message_pos, copysize
1645 + sizeof(struct FragmentationHeader), copyoffset,
1646 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1649 if (copyoffset >= fm->message_size)
1652 GNUNET_ERROR_TYPE_ERROR,
1653 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1654 copyoffset, fm->message_size, WLAN_MTU
1655 - sizeof(struct FragmentationHeader), copysize,
1658 GNUNET_assert(copyoffset < fm->message_size);
1660 fragheader.header.size = htons(copysize
1661 + sizeof(struct FragmentationHeader));
1662 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1665 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1666 + sizeof(struct GNUNET_MessageHeader);
1667 msgheader = GNUNET_malloc(size);
1668 msgheader->size = htons(size);
1669 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1671 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1672 getRadiotapHeader(plugin, session, radioHeader);
1674 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1675 getWlanHeader(ieeewlanheader, &(fm->session->addr), plugin, size);
1678 //could be faster if content is just send and not copyed before
1679 //fragmentheader is needed
1680 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1681 memcpy(&ieeewlanheader[1], &fragheader,
1682 sizeof(struct FragmentationHeader));
1683 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1684 memcpy(&fragheaderptr[1], copystart, copysize);
1686 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1688 if (bytes == GNUNET_SYSERR)
1691 GNUNET_ERROR_TYPE_ERROR,
1692 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1693 errno, strerror(errno));
1696 GNUNET_assert(bytes != GNUNET_SYSERR);
1698 //check if this was the last fragment of this message, if true then queue at the end of the list
1699 if (copysize + copyoffset >= fm->message_size)
1701 GNUNET_assert(copysize + copyoffset == fm->message_size);
1703 GNUNET_CONTAINER_heap_update_cost(
1704 plugin->pending_Fragment_Messages, fm->node, MIN(
1705 fm->timeout.abs_value, fm->next_ack.abs_value));
1706 // if fragments have opimized timeouts
1707 //sort_fragment_into_queue(plugin,fm);
1710 #if DEBUG_wlan_retransmission
1712 GNUNET_ERROR_TYPE_DEBUG,
1713 "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1714 fm->message_id_out, fm->message_id_out, fm->message_pos,
1715 fm->message_size, GNUNET_TIME_absolute_get_remaining(
1721 GNUNET_CONTAINER_heap_update_cost(
1722 plugin->pending_Fragment_Messages, fm->node,
1723 GNUNET_TIME_absolute_get().abs_value);
1728 finish = GNUNET_malloc(sizeof( struct Finish_send));
1729 finish->plugin = plugin;
1730 finish->msgheader = (char *) msgheader + bytes;
1731 finish->size = size - bytes;
1732 finish->msgstart = msgheader;
1734 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1736 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1737 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1738 &finish_sending, finish);
1743 GNUNET_free(msgheader);
1744 set_next_send(plugin);
1751 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1752 "do_transmit did nothing, should not happen!\n");
1756 * Another peer has suggested an address for this
1757 * peer and transport plugin. Check that this could be a valid
1758 * address. If so, consider adding it to the list
1761 * @param cls closure
1762 * @param addr pointer to the address
1763 * @param addrlen length of addr
1764 * @return GNUNET_OK if this is a plausible address for this peer
1768 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1770 //struct Plugin *plugin = cls;
1772 /* check if the address is plausible; if so,
1773 add it to our list! */
1775 GNUNET_assert(cls !=NULL);
1776 //FIXME mitm is not checked
1777 //Mac Address has 6 bytes
1780 /* TODO check for bad addresses like multicast, broadcast, etc */
1784 return GNUNET_SYSERR;
1788 * Function that can be used by the transport service to transmit
1789 * a message using the plugin.
1791 * @param cls closure
1792 * @param target who should receive this message
1793 * @param priority how important is the message
1794 * @param msgbuf the message to transmit
1795 * @param msgbuf_size number of bytes in 'msgbuf'
1796 * @param timeout when should we time out
1797 * @param session which session must be used (or NULL for "any")
1798 * @param addr the address to use (can be NULL if the plugin
1799 * is "on its own" (i.e. re-use existing TCP connection))
1800 * @param addrlen length of the address in bytes
1801 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1802 * otherwise the plugin may use other addresses or
1803 * existing connections (if available)
1804 * @param cont continuation to call once the message has
1805 * been transmitted (or if the transport is ready
1806 * for the next transmission call; or if the
1807 * peer disconnected...)
1808 * @param cont_cls closure for cont
1809 * @return number of bytes used (on the physical network, with overheads);
1810 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1811 * and does NOT mean that the message was not transmitted (DV)
1814 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1815 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1816 struct GNUNET_TIME_Relative timeout, struct Session *session,
1817 const void *addr, size_t addrlen, int force_address,
1818 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1820 struct Plugin * plugin = cls;
1821 struct PendingMessage * newmsg;
1822 struct WlanHeader * wlanheader;
1824 //check if msglen > 0
1825 GNUNET_assert(msgbuf_size > 0);
1827 //get session if needed
1828 if (session == NULL)
1830 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1832 session = get_session(plugin, addr);
1836 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1837 _("Wlan Address len %d is wrong\n"), addrlen);
1842 //TODO target "problem" not solved
1843 //if (session->target != NULL){
1844 // GNUNET_assert(session->target == *target);
1846 session->target = *target;
1852 //queue message in session
1853 //test if there is no other message in the "queue"
1854 //FIXME: to many send requests
1855 //GNUNET_assert (session->pending_message == NULL);
1856 if (session->pending_message != NULL)
1858 newmsg = session->pending_message;
1860 GNUNET_ERROR_TYPE_ERROR,
1861 "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",
1862 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1863 session->fragment_messages_out_count);
1864 if (session->pending_message2 != NULL)
1867 GNUNET_ERROR_TYPE_ERROR,
1868 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1873 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1874 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1875 wlanheader = (struct WlanHeader *) newmsg->msg;
1876 //copy msg to buffer, not fragmented / segmented yet, but with message header
1877 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1878 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1879 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1880 wlanheader->crc = 0;
1881 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1882 wlanheader->crc = htonl(getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)));
1883 //GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Wlan message Header crc: %u, %u\n",getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)), wlanheader->crc);
1884 //hexdump(newmsg->msg, msgbuf_size + sizeof(struct WlanHeader));
1886 newmsg->transmit_cont = cont;
1887 newmsg->transmit_cont_cls = cont_cls;
1888 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1890 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1892 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1894 if (session->pending_message == NULL)
1896 session->pending_message = newmsg;
1900 session->pending_message2 = newmsg;
1904 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1905 "New message for %p with size (incl wlan header) %u added\n", session,
1906 newmsg->message_size);
1910 queue_session(plugin, session);
1912 check_fragment_queue(plugin);
1913 //FIXME not the correct size
1919 * Iterate over the fragment messages of the given session.
1921 * @param cls argument to give to iterator
1922 * @param node node to iterate over
1923 * @param element value stored at the node
1924 * @param cost cost associated with the node
1925 * @return GNUNET_YES if we should continue to iterate,
1929 free_fragment_message_from_session(void *cls,
1930 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1931 GNUNET_CONTAINER_HeapCostType cost)
1933 struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
1934 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1936 if (fm->session == pair->session)
1939 free_fragment_message(pair->plugin, fm);
1946 * Search for fragment message with given id and session
1948 * @param cls argument to give to iterator
1949 * @param node node to iterate over
1950 * @param element value stored at the node
1951 * @param cost cost associated with the node
1952 * @return GNUNET_YES if we should continue to iterate,
1956 search_fragment_message_from_session_and_id(void *cls,
1957 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1958 GNUNET_CONTAINER_HeapCostType cost)
1960 struct Session_id_fragment_triple * triple =
1961 (struct Session_id_fragment_triple *) cls;
1962 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1964 if ((fm->session == triple->session) && (fm->message_id_out
1965 == triple->message_id))
1975 * function to get the message in the fragement queue (out) of a session with a specific id
1976 * @param session pointer to the session
1977 * @param message_id id of the message
1978 * @return pointer to the struct FragmentMessage
1980 static struct FragmentMessage *
1981 get_fragment_message_from_session_and_id(struct Plugin * plugin,
1982 struct Session * session, uint32_t message_id)
1984 struct Session_id_fragment_triple triple;
1985 triple.session = session;
1986 triple.message_id = message_id;
1988 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1989 &search_fragment_message_from_session_and_id, &triple);
1994 * function to get the receive message of a session
1995 * @param plugin pointer to the plugin struct
1996 * @param session session this fragment belongs to
1998 static struct Receive_Message_Queue *
1999 get_receive_message_from_session(struct Plugin * plugin,
2000 struct Session * session)
2002 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2003 while (rec_message != NULL)
2005 if (rec_message->session == session)
2009 rec_message = rec_message->next;
2015 * Function to dispose the fragments received for a message and the message
2016 * @param plugin pointer to the plugin struct
2017 * @param rec_message pointer to the struct holding the message which should be freed
2020 free_receive_message(struct Plugin* plugin,
2021 struct Receive_Message_Queue * rx_message)
2023 GNUNET_assert(rx_message !=NULL);
2024 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
2025 struct Receive_Fragment_Queue * rec_queue2;
2027 while (rec_queue != NULL)
2029 rec_queue2 = rec_queue;
2030 rec_queue = rec_queue->next;
2031 GNUNET_free(rec_queue2);
2034 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
2036 GNUNET_assert(plugin->pending_receive_messages > 0);
2037 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
2039 plugin->pending_receive_messages--;
2040 rx_message->session->fragment_messages_in_count--;
2041 GNUNET_free(rx_message);
2045 * function to get the receive message of a session
2046 * @param plugin pointer to the plugin struct
2047 * @param session session this fragment belongs to
2050 check_receive_message_timeouts(struct Plugin * plugin, struct Session * session)
2052 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2053 while (rec_message != NULL)
2055 if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
2058 free_receive_message(plugin, rec_message);
2060 rec_message = rec_message->next;
2067 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
2069 struct Sessionqueue * pendingsession;
2070 struct Sessionqueue * pendingsession_tmp;
2071 struct PendingMessage * pm;
2072 struct Receive_Message_Queue * receive_queue;
2073 struct Plugin_Session_pair pair;
2076 GNUNET_assert(queue != NULL);
2077 GNUNET_assert(queue->content != NULL);
2080 //is this session pending for send
2081 pendingsession = plugin->pending_Sessions_head;
2082 while (pendingsession != NULL)
2084 pendingsession_tmp = pendingsession->next;
2085 if (pendingsession->content == queue->content)
2087 plugin->pendingsessions--;
2088 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2089 plugin->pending_Sessions_tail,
2091 GNUNET_free(pendingsession);
2093 GNUNET_assert (check == 0);
2096 pendingsession = pendingsession_tmp;
2099 //is something of this session in the fragment queue?
2100 pair.plugin = plugin;
2101 pair.session = queue->content;
2102 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
2103 &free_fragment_message_from_session, &pair);
2105 //dispose all received fragments
2106 receive_queue = get_receive_message_from_session(plugin, queue->content);
2107 while (receive_queue != NULL)
2109 free_receive_message(plugin, receive_queue);
2110 receive_queue = get_receive_message_from_session(plugin, queue->content);
2113 // remove PendingMessage
2114 pm = queue->content->pending_message;
2117 GNUNET_free_non_null(pm->msg);
2121 // remove PendingMessage
2122 pm = queue->content->pending_message2;
2125 GNUNET_free_non_null(pm->msg);
2129 GNUNET_CONTAINER_DLL_remove(plugin->sessions,
2130 plugin->sessions_tail,
2132 GNUNET_free(queue->content);
2134 plugin->session_count--;
2135 check_fragment_queue(plugin);
2139 * Function that can be used to force the plugin to disconnect
2140 * from the given peer and cancel all previous transmissions
2141 * (and their continuation).
2143 * @param cls closure
2144 * @param target peer from which to disconnect
2147 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
2149 struct Plugin *plugin = cls;
2150 struct Sessionqueue * queue = plugin->sessions;
2152 // just look at all the session for the needed one
2153 while (queue != NULL)
2155 // content is never NULL
2156 GNUNET_assert (queue->content != NULL);
2157 if (memcmp(target, &(queue->content->target),
2158 sizeof(struct GNUNET_PeerIdentity)) == 0)
2160 free_session(plugin, queue);
2164 queue = queue->next;
2169 * Convert the transports address to a nice, human-readable
2172 * @param cls closure
2173 * @param type name of the transport that generated the address
2174 * @param addr one of the addresses of the host, NULL for the last address
2175 * the specific address format depends on the transport
2176 * @param addrlen length of the address
2177 * @param numeric should (IP) addresses be displayed in numeric form?
2178 * @param timeout after how long should we give up?
2179 * @param asc function to call on each string
2180 * @param asc_cls closure for asc
2183 wlan_plugin_address_pretty_printer(void *cls, const char *type,
2184 const void *addr, size_t addrlen, int numeric,
2185 struct GNUNET_TIME_Relative timeout,
2186 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
2189 const unsigned char * input;
2191 //GNUNET_assert(cls !=NULL);
2194 /* invalid address (MAC addresses have 6 bytes) */
2199 input = (const unsigned char*) addr;
2200 GNUNET_snprintf(ret, sizeof(ret),
2201 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2202 input[0], input[1], input[2], input[3], input[4], input[5]);
2207 * Function to test if fragment number already exists in the fragments received
2209 * @param rec_message message this fragment belongs to
2210 * @param fh Fragmentheader of the fragment
2211 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2214 is_double_msg(struct Receive_Message_Queue * rx_msg,
2215 struct FragmentationHeader * fh)
2218 return testBit((char *) &rx_msg->received_fragments, ntohs(
2219 fh->fragment_off_or_num));
2224 * Function to insert a fragment in a queue of a message
2225 * @param session session the fragment belongs to
2226 * @param rec_queue fragment to add
2229 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2230 struct Receive_Fragment_Queue * rx_frag)
2232 GNUNET_assert(rx_message != NULL);
2233 GNUNET_assert(rx_frag != NULL);
2235 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2236 struct WlanHeader * wlanheader;
2238 //this is the first fragment of the message (fragment id 0)
2239 if (rx_frag->num == 0)
2241 wlanheader = (struct WlanHeader *) rx_frag->msg;
2242 rx_message->rec_size = ntohs(wlanheader->header.size);
2246 while (rx_frag2 != NULL)
2248 if (rx_frag2->num > rx_frag->num)
2250 //next element number is grater than the current num
2251 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2252 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2255 rx_frag2 = rx_frag2->next;
2258 //no element has a grater number
2259 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2261 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2265 * handels the data after all fragments are put together
2267 * @param session_light
2268 * @param hdr pointer to the data
2271 wlan_data_message_handler(void *cls, void *client,
2272 const struct GNUNET_MessageHeader *hdr)
2274 struct Plugin * plugin = (struct Plugin*) cls;
2275 struct Session_light * session_light = (struct Session_light *) client;
2276 struct WlanHeader * wlanheader;
2277 struct Session * session;
2278 //const char * tempmsg;
2279 const struct GNUNET_MessageHeader * temp_hdr;
2280 struct GNUNET_PeerIdentity tmptarget;
2283 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2288 GNUNET_ERROR_TYPE_DEBUG,
2289 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2293 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2294 + sizeof(struct GNUNET_MessageHeader))
2296 //packet not big enought
2300 GNUNET_assert(session_light != NULL);
2301 if (session_light->session == NULL)
2303 session_light->session = search_session(plugin, &session_light->addr);
2305 session = session_light->session;
2306 wlanheader = (struct WlanHeader *) hdr;
2308 //tempmsg = (char*) &wlanheader[1];
2309 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2310 crc = ntohl(wlanheader->crc);
2311 wlanheader->crc = 0;
2312 if (getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)) != crc)
2314 //wrong crc, dispose message
2315 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2316 "Wlan message Header crc was wrong: %u != %u\n",getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)), crc);
2317 hexdump((void *)hdr, ntohs(hdr->size));
2321 //if not in session list
2322 if (session == NULL)
2326 GNUNET_ERROR_TYPE_DEBUG,
2327 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2328 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2329 sizeof(struct WlanHeader));
2331 //try if it is a hello message
2332 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2333 + sizeof(struct WlanHeader))
2335 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2337 if (GNUNET_HELLO_get_id(
2338 (const struct GNUNET_HELLO_Message *) temp_hdr,
2339 &tmptarget) == GNUNET_OK)
2341 session = create_session(plugin, &session_light->addr);
2342 session_light->session = session;
2343 memcpy(&session->target, &tmptarget,
2344 sizeof(struct GNUNET_PeerIdentity));
2348 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2349 "WLAN client not in session list and hello message not okay\n");
2356 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2357 "WLAN client not in session list and not a hello message\n");
2364 GNUNET_ERROR_TYPE_WARNING,
2365 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2366 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2367 sizeof(struct WlanHeader));
2372 //"receive" the message
2375 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2376 (const char *) temp_hdr,
2377 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2383 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2384 "wlan_data_message_handler got wrong message type\n");
2390 * Function to check if all fragments of a message have been received
2391 * @param plugin the plugin handle
2392 * @param session_light information of the message sender
2393 * @param session session the message belongs to
2394 * @param rec_message pointer to the message that should be checked
2398 check_rx_finished_msg(struct Plugin* plugin,
2399 struct Session_light * session_light, struct Session * session,
2400 struct Receive_Message_Queue * rx_message)
2402 GNUNET_assert(rx_message !=NULL);
2404 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2405 int packetsize = rx_message->rec_size;
2409 uint64_t bitfield = 0;
2412 //check if first fragment is present
2413 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2417 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2419 else if (packetsize < sizeof(struct WlanHeader)
2420 + sizeof(struct GNUNET_MessageHeader))
2423 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2425 free_receive_message(plugin, rx_message);
2429 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2431 bitfield = ~bitfield;
2432 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2433 if (rx_message->received_fragments == bitfield)
2436 while (rx_frag != NULL)
2438 sum += rx_frag->size;
2439 rx_frag = rx_frag->next;
2441 //sum should always be smaller or equal of
2442 GNUNET_assert(sum <= packetsize);
2443 if (sum == packetsize)
2447 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2448 "check_rec_finished_msg: A message for %p is complete\n", session);
2453 //copy fragments together
2454 //msg = GNUNET_malloc(packetsize);
2455 rx_frag = rx_message->frag_head;
2457 /*while (rx_frag != NULL)
2459 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2460 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2461 aktnum += rx_frag->size;
2462 rx_frag = rx_frag->next;
2465 while (rx_frag != NULL)
2467 if (rx_frag->next != NULL)
2469 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2470 session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
2475 //if it is the last fragment just kill all leftover
2476 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2477 session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
2480 rx_frag = rx_frag->next;
2482 session->message_id_backlog[session->message_id_backlog_pos] = rx_message->message_id_in;
2483 session->message_id_backlog_pos = (session->message_id_backlog_pos + 1) % MESSAGE_ID_BACKLOG_SIZE;
2484 free_receive_message(plugin, rx_message);
2485 //call wlan_process_helper to process the message
2486 //wlan_data_message_handler(plugin, session_light,
2487 // (struct GNUNET_MessageHeader*) msg);
2488 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2498 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2501 GNUNET_assert(client != NULL);
2502 GNUNET_assert(cls != NULL);
2503 struct Session * session = (struct Session *) client;
2504 struct Plugin * plugin = (struct Plugin *) cls;
2506 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2507 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2508 distance[0].value = htonl(1);
2509 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2510 distance[1].value = htonl(0);
2513 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2514 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2515 wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
2519 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2520 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2521 (const char*) &session->addr, sizeof(session->addr));
2525 * function to add an ack to send it for a received fragment
2526 * @param plugin pointer to the global plugin structure
2527 * @param session pointer to the session this ack belongs to
2528 * @param bitfield bitfield to send
2529 * @param fh pointer to the fragmentation header which we would like to acknolage
2533 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2534 uint64_t bitfield, struct FragmentationHeader * fh)
2536 struct AckSendQueue * ack;
2538 GNUNET_assert(plugin != NULL);
2539 GNUNET_assert(session != NULL);
2540 GNUNET_assert(fh != NULL);
2542 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2543 ack->fragments_field = bitfield;
2544 ack->message_id = ntohl(fh->message_id);
2545 ack->session = session;
2547 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2548 plugin->ack_send_queue_tail, ack);
2553 * function to get the receive message from the message id and the session
2554 * @param plugin pointer to the plugin struct
2555 * @param session session this fragment belongs to
2556 * @param message_id id of the message
2559 struct Receive_Message_Queue *
2560 get_receive_message(struct Plugin * plugin, struct Session * session,
2561 uint32_t message_id)
2563 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2564 while (rec_message != NULL)
2566 if ((rec_message->message_id_in == message_id) && (rec_message->session
2571 rec_message = rec_message->next;
2577 * function to insert a received fragment into the right fragment queue of the right message
2578 * @param plugin pointer to the plugin struct
2579 * @param session_light pointer to the session_light struct of this message
2580 * @param session session this fragment belongs to
2581 * @param fh pointer to the header of the fragment
2582 * @return new fragment bitfield for the message
2586 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2587 struct Session_light * session_light, struct Session * session,
2588 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2590 struct Receive_Fragment_Queue * rx_frag = NULL;
2591 struct Receive_Message_Queue * rx_message;
2592 const char * tempmsg = (char*) &fh[1];
2593 uint64_t retval = 0;
2596 //TODO fragments do not timeout
2597 //check if message_id is right or it is a new msg
2598 GNUNET_assert(fh != NULL);
2600 //check for receive of old messages
2601 for (i = 0; i< MESSAGE_ID_BACKLOG_SIZE; i++)
2603 if (session->message_id_backlog[i] == ntohl(fh->message_id) ){
2604 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2609 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2611 if (rx_message == NULL)
2613 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2615 check_receive_message_timeouts(plugin, session);
2618 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2621 //new message incoming
2622 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2623 rx_message->message_id_in = ntohl(fh->message_id);
2624 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2625 rx_message->session = session;
2626 rx_message->received_fragments = 0;
2628 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2630 session->fragment_messages_in_count++;
2631 plugin->pending_receive_messages++;
2635 GNUNET_ERROR_TYPE_DEBUG,
2636 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2637 rx_message->message_id_in, session->fragment_messages_in_count,
2638 plugin->pending_receive_messages);
2645 GNUNET_ERROR_TYPE_INFO,
2646 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
2647 get_receive_message_from_session(plugin, session)->message_id_in);
2648 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2654 rx_message->timeout = GNUNET_TIME_absolute_add(
2655 GNUNET_TIME_absolute_get(),
2656 MESSAGE_IN_TIMEOUT);
2658 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2662 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2663 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2664 rx_frag->size = ntohs(fh->header.size)
2665 - sizeof(struct FragmentationHeader);
2666 rx_frag->num = ntohs(fh->fragment_off_or_num);
2667 rx_frag->msg = (char*) &(rx_frag[1]);
2668 //copy msg to buffer
2669 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2670 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2671 insert_fragment_in_queue(rx_message, rx_frag);
2673 retval = rx_message->received_fragments;
2677 GNUNET_ERROR_TYPE_DEBUG,
2678 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2679 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2680 rx_message->received_fragments, session);
2683 check_rx_finished_msg(plugin, session_light, session, rx_message);
2687 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2688 retval = rx_message->received_fragments;
2696 * Function used for to process the data received from the wlan interface
2698 * @param cls the plugin handle
2699 * @param session_light FIXME: document
2700 * @param hdr hdr of the GNUNET_MessageHeader
2703 wlan_data_helper(void *cls, struct Session_light * session_light,
2704 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2706 struct Plugin *plugin = cls;
2707 struct Session * session;
2709 struct FragmentationHeader * fh;
2710 struct FragmentationAckHeader * fah;
2711 struct FragmentMessage * fm;
2713 const char * tempmsg;
2715 uint64_t fragment_bitfield = 0;
2718 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2721 //TODO better DOS protection, error handling
2722 //TODO test first than create session
2723 GNUNET_assert(session_light != NULL);
2727 GNUNET_ERROR_TYPE_DEBUG,
2728 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2729 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2730 session_light->addr.mac, 6));
2733 if (session_light->session == NULL)
2735 session_light->session = get_session(plugin, &session_light->addr);
2737 GNUNET_assert(GNUNET_HELLO_get_id(
2738 (const struct GNUNET_HELLO_Message *) &hdr[1],
2739 &(session_light->session->target) ) != GNUNET_SYSERR);
2745 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2748 GNUNET_assert(session_light != NULL);
2749 if (session_light->session == NULL)
2751 session_light->session = search_session(plugin, &session_light->addr);
2753 session = session_light->session;
2755 fh = (struct FragmentationHeader *) hdr;
2756 tempmsg = (char*) &fh[1];
2760 GNUNET_ERROR_TYPE_DEBUG,
2761 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2762 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2763 hdr->size), wlan_plugin_address_to_string(NULL,
2764 session_light->addr.mac, 6));
2767 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2769 //wrong crc, dispose message
2770 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2774 //if in the session list
2775 if (session != NULL)
2777 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2778 session_light, session, fh, rxinfo);
2784 GNUNET_ERROR_TYPE_INFO,
2785 "WLAN client not in session list, fragment num %u, message id %u\n",
2786 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2788 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
2789 tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
2790 GNUNET_YES, GNUNET_NO);
2791 //wlan_data_message_handler(plugin, session_light,
2792 // (struct GNUNET_MessageHeader *) tempmsg);
2793 session = session_light->session;
2794 //test if a session was created
2795 if (session == NULL)
2799 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2802 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2803 set_next_send(plugin);
2809 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2814 GNUNET_ERROR_TYPE_DEBUG,
2815 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2816 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2817 session_light->addr.mac, 6));
2820 GNUNET_assert(session_light != NULL);
2821 if (session_light->session == NULL)
2823 session_light->session = search_session(plugin, &session_light->addr);
2824 GNUNET_assert(session_light->session != NULL);
2826 session = session_light->session;
2827 fah = (struct FragmentationAckHeader *) hdr;
2828 fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
2834 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
2835 fah->fragment_field);
2836 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
2838 #if DEBUG_wlan_retransmission
2839 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
2840 fm->message_id_out, fm->ack_bitfield);
2842 check_finished_fragment(plugin, fm);
2843 set_next_send(plugin);
2848 //GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2849 // "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2850 // fah->message_id));
2859 GNUNET_ERROR_TYPE_INFO,
2860 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2861 ntohs(hdr->type), ntohs(hdr->size));
2867 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2868 "Helper finished\n");
2875 macprinter(const u_int8_t * mac)
2877 static char macstr[20];
2879 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2880 mac[2], mac[3], mac[4], mac[5]);
2885 * Function used for to process the data from the suid process
2887 * @param cls the plugin handle
2888 * @param client client that send the data (not used)
2889 * @param hdr header of the GNUNET_MessageHeader
2892 wlan_process_helper(void *cls, void *client,
2893 const struct GNUNET_MessageHeader *hdr)
2895 struct Plugin *plugin = cls;
2896 struct ieee80211_frame * wlanIeeeHeader = NULL;
2897 struct Session_light * session_light = NULL;
2898 struct Radiotap_rx * rxinfo;
2899 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2904 switch (ntohs(hdr->type))
2906 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2909 GNUNET_ERROR_TYPE_DEBUG,
2910 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2914 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2915 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2916 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2919 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2920 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2921 hdr->size), sizeof(struct ieee80211_frame)
2922 + sizeof(struct GNUNET_MessageHeader));
2925 /* FIXME: restart SUID process */
2928 rxinfo = (struct Radiotap_rx *) &hdr[1];
2929 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2931 //process only if it is an broadcast or for this computer both with the gnunet bssid
2934 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
2935 sizeof(struct MacAddress)) == 0)
2937 //check for broadcast or mac
2938 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2939 sizeof(struct MacAddress) == 0) || memcmp(
2940 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2941 sizeof(struct MacAddress)) == 0)
2944 // process the inner data
2947 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2948 - sizeof(struct GNUNET_MessageHeader)
2949 - sizeof(struct Radiotap_rx);
2951 session_light = GNUNET_malloc(sizeof(struct Session_light));
2952 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2953 sizeof(struct MacAddress));
2954 //session_light->session = search_session(plugin,session_light->addr);
2957 while (pos < datasize)
2959 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2962 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2963 pos += ntohs(temp_hdr->size);
2968 GNUNET_free(session_light);
2973 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2974 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2975 wlanIeeeHeader->i_addr1));
2982 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2983 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2984 wlanIeeeHeader->i_addr2));
2988 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2989 //TODO more control messages
2990 //TODO use struct wlan_helper_control
2991 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2994 /* FIXME: restart SUID process */
2997 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2999 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3000 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
3001 wlan_plugin_address_to_string(cls, &plugin->mac_address,
3002 sizeof(struct MacAddress)));
3004 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
3005 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
3014 * We have been notified that wlan-helper has written something to stdout.
3015 * Handle the output, then reschedule this function to be called again once
3016 * more is available.
3018 * @param cls the plugin handle
3019 * @param tc the scheduling context
3022 wlan_plugin_helper_read(void *cls,
3023 const struct GNUNET_SCHEDULER_TaskContext *tc)
3025 struct Plugin *plugin = cls;
3026 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3028 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
3031 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
3034 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
3039 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3040 _("Finished reading from wlan-helper stdout with code: %d\n"),
3045 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
3046 GNUNET_NO, GNUNET_NO);
3048 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3049 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3050 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3051 &wlan_plugin_helper_read, plugin);
3055 * Start the gnunet-wlan-helper process.
3057 * @param plugin the transport plugin
3058 * @param testmode should we use the dummy driver for testing?
3059 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
3062 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
3064 const char * filenamehw = "gnunet-transport-wlan-helper";
3065 const char * filenameloopback = "gnunet-transport-wlan-helper-dummy";
3066 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
3067 if (plugin->server_stdout == NULL)
3068 return GNUNET_SYSERR;
3070 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
3071 if (plugin->server_stdin == NULL)
3072 return GNUNET_SYSERR;
3075 /* Start the server process */
3081 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3082 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filenamehw,
3083 plugin->interface, testmode);
3086 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3087 plugin->server_stdout, filenamehw, filenamehw, plugin->interface, NULL);
3089 else if (testmode == 1)
3093 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3094 "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n", filenameloopback,
3095 plugin->interface, testmode);
3098 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3099 plugin->server_stdout, filenameloopback, filenameloopback, "1", NULL);
3101 else if (testmode == 2)
3104 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3105 "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n", filenameloopback,
3106 plugin->interface, testmode);
3108 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3109 plugin->server_stdout, filenameloopback, filenameloopback, "2", NULL);
3111 if (plugin->server_proc == NULL)
3114 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3115 "Failed to start gnunet-wlan-helper process\n");
3117 return GNUNET_SYSERR;
3120 /* Close the write end of the read pipe */
3121 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
3123 /* Close the read end of the write pipe */
3124 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
3126 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
3127 GNUNET_DISK_PIPE_END_READ);
3128 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
3129 GNUNET_DISK_PIPE_END_WRITE);
3131 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3134 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3135 "Adding server_read_task for the wlan-helper\n");
3138 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3139 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3140 &wlan_plugin_helper_read, plugin);
3146 * Exit point from the plugin.
3147 * @param cls pointer to the api struct
3152 libgnunet_plugin_transport_wlan_done(void *cls)
3154 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3155 struct Plugin *plugin = api->cls;
3156 struct Sessionqueue * queue = plugin->sessions;
3157 struct Sessionqueue * queue_next;
3158 struct FragmentMessage * fm;
3161 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3162 "libgnunet_plugin_transport_wlan_done started\n");
3166 GNUNET_DISK_pipe_close(plugin->server_stdout);
3167 GNUNET_DISK_pipe_close(plugin->server_stdin);
3168 GNUNET_OS_process_kill(plugin->server_proc,9);
3169 GNUNET_OS_process_close(plugin->server_proc);
3172 GNUNET_assert (cls !=NULL);
3174 while (queue != NULL)
3176 queue_next = queue->next;
3177 free_session(plugin, queue);
3181 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
3183 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
3184 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3186 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
3188 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
3189 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3191 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
3193 GNUNET_SCHEDULER_cancel(plugin->server_read_task);
3194 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3197 if (plugin->suid_tokenizer != NULL)
3198 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
3200 if (plugin->data_tokenizer != NULL)
3201 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3203 if (plugin->fragment_tokenizer != NULL)
3204 GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
3206 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3207 plugin->pending_Fragment_Messages);
3211 free_fragment_message(plugin, fm);
3212 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3213 plugin->pending_Fragment_Messages);
3216 GNUNET_free_non_null(plugin->interface);
3217 GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
3218 GNUNET_free (plugin);
3224 * Entry point for the plugin.
3226 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3227 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3230 libgnunet_plugin_transport_wlan_init(void *cls)
3232 //struct GNUNET_SERVICE_Context *service;
3233 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3234 struct GNUNET_TRANSPORT_PluginFunctions *api;
3235 struct Plugin *plugin;
3236 static unsigned long long testmode = 0;
3238 GNUNET_assert(cls !=NULL);
3240 plugin = GNUNET_malloc (sizeof (struct Plugin));
3242 plugin->pendingsessions = 0;
3243 plugin->session_count = 0;
3244 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3245 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3246 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3247 plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
3248 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3250 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3253 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3254 plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
3255 &wlan_data_message_handler, plugin);
3257 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3258 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3260 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3262 api->send = &wlan_plugin_send;
3263 api->disconnect = &wlan_plugin_disconnect;
3264 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3265 api->check_address = &wlan_plugin_address_suggested;
3266 api->address_to_string = &wlan_plugin_address_to_string;
3269 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3271 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3272 "transport-wlan", "TESTMODE", &testmode))
3273 testmode = 0; //default value
3276 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3278 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3279 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3281 libgnunet_plugin_transport_wlan_done(api);
3287 set_next_beacon_time(plugin);
3289 wlan_transport_start_wlan_helper(plugin, testmode);
3292 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3298 /* end of plugin_transport_wlan.c */