2 This file is part of GNUnet
3 (C) 2010 2011 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
27 //TODO split rx and tx structures for better handling
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_statistics_service.h"
34 #include "gnunet_transport_service.h"
35 #include "gnunet_transport_plugin.h"
36 #include "plugin_transport_wlan.h"
37 #include "gnunet_common.h"
38 #include "gnunet_crypto_lib.h"
39 #include "gnunet_fragmentation_lib.h"
40 #include "gnunet_constants.h"
44 #define PROTOCOL_PREFIX "wlan"
46 #define PLUGIN_LOG_NAME "wlan-plugin"
54 * time out of a session
56 #define SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
59 * time out of a mac endpoint
61 #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
64 * scaling factor for hello beacon
66 #define HELLO_BEACON_SCALING_FACTOR 30
69 * scaling factor for restarting the helper
71 #define HELPER_RESTART_SCALING_FACTOR 2
74 * max size of fragment queue
76 #define FRAGMENT_QUEUE_SIZE 10
78 * max messages in fragment queue per session/client
80 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
83 * max messages in fragment queue per MAC
85 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT 1
88 * max messages in in queue
90 #define MESSAGES_IN_QUEUE_SIZE 10
92 * max messages in in queue per session/client
94 #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 1
97 * LLC fields for better compatibility
99 #define WLAN_LLC_DSAP_FIELD 0x1f
100 #define WLAN_LLC_SSAP_FIELD 0x1f
106 #define DEBUG_wlan GNUNET_EXTRA_LOGGING
107 #define DEBUG_wlan_retransmission GNUNET_EXTRA_LOGGING
108 #define DEBUG_wlan_ip_udp_packets_on_air GNUNET_NO
109 #define DEBUG_wlan_msg_dump GNUNET_EXTRA_LOGGING
112 #define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
114 #define IEEE80211_FC0_VERSION_MASK 0x03
115 #define IEEE80211_FC0_VERSION_SHIFT 0
116 #define IEEE80211_FC0_VERSION_0 0x00
117 #define IEEE80211_FC0_TYPE_MASK 0x0c
118 #define IEEE80211_FC0_TYPE_SHIFT 2
119 #define IEEE80211_FC0_TYPE_MGT 0x00
120 #define IEEE80211_FC0_TYPE_CTL 0x04
121 #define IEEE80211_FC0_TYPE_DATA 0x08
124 * generic definitions for IEEE 802.11 frames
126 struct ieee80211_frame
130 u_int8_t i_addr1[IEEE80211_ADDR_LEN];
131 u_int8_t i_addr2[IEEE80211_ADDR_LEN];
132 u_int8_t i_addr3[IEEE80211_ADDR_LEN];
138 * Encapsulation of all of the state of the plugin.
145 struct GNUNET_TRANSPORT_PluginEnvironment *env;
148 * List of open connections. head
150 struct MacEndpoint *mac_head;
153 * List of open connections. tail
155 struct MacEndpoint *mac_tail;
158 * Number of connections
160 unsigned int mac_count;
163 * encapsulation of data from the local wlan helper program
165 struct GNUNET_SERVER_MessageStreamTokenizer *suid_tokenizer;
168 * encapsulation of packets received from the wlan helper
170 struct GNUNET_SERVER_MessageStreamTokenizer *data_tokenizer;
173 * stdout pipe handle for the gnunet-helper-transport-wlan process
175 struct GNUNET_DISK_PipeHandle *server_stdout;
178 * stdout file handle for the gnunet-helper-transport-wlan process
180 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
183 * stdin pipe handle for the gnunet-helper-transport-wlan process
185 struct GNUNET_DISK_PipeHandle *server_stdin;
188 * stdin file handle for the gnunet-helper-transport-wlan process
190 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
193 * ID of the gnunet-wlan-server std read task
195 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
198 * ID of the gnunet-wlan-server std read task
200 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
203 * ID of the delay task for writing
205 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
208 * The process id of the wlan process
210 struct GNUNET_OS_Process *server_proc;
213 * The interface of the wlan card given to us by the user.
218 * Mode of operation for the helper, 0 = normal, 1 = first loopback, 2 = second loopback
220 long long unsigned int testmode;
223 * The mac_address of the wlan card given to us by the helper.
225 struct MacAddress mac_address;
228 * Sessions currently pending for transmission
231 struct Sessionqueue *pending_Sessions_head;
234 * Sessions currently pending for transmission
235 * to a peer (tail), if any.
237 struct Sessionqueue *pending_Sessions_tail;
240 * number of pending sessions
242 unsigned int pendingsessions;
245 * Messages in the sending queues
247 int pending_Fragment_Messages;
250 * messages ready for send, head
252 struct FragmentMessage_queue *sending_messages_head;
254 * messages ready for send, tail
256 struct FragmentMessage_queue *sending_messages_tail;
258 * time of the next "hello-beacon"
260 struct GNUNET_TIME_Absolute beacon_time;
263 * queue to send acks for received fragments (head)
265 struct AckSendQueue *ack_send_queue_head;
268 * queue to send acks for received fragments (tail)
270 struct AckSendQueue *ack_send_queue_tail;
273 * Tracker for bandwidth limit
275 struct GNUNET_BANDWIDTH_Tracker tracker;
278 * saves the current state of the helper process
280 int helper_is_running;
284 * Struct to store data if file write did not accept the whole packet
289 * pointer to the global plugin struct
291 struct Plugin *plugin;
294 * head of the next part to send to the helper
296 char *head_of_next_write;
299 * Start of the message to send, needed for free
301 struct GNUNET_MessageHeader *msgstart;
310 * Queue of sessions, for the general session queue and the pending session queue
315 struct Sessionqueue *next;
316 struct Sessionqueue *prev;
317 struct Session *content;
318 #if !HAVE_UNALIGNED_64_ACCESS
319 void *dummy; /* for alignment, see #1909 */
324 * Queue of fragmented messages, for the sending queue of the plugin
327 struct FragmentMessage_queue
329 struct FragmentMessage_queue *next;
330 struct FragmentMessage_queue *prev;
331 struct FragmentMessage *content;
335 * Queue for the fragments received
338 struct Receive_Fragment_Queue
340 struct Receive_Fragment_Queue *next;
341 struct Receive_Fragment_Queue *prev;
345 struct Radiotap_rx rxinfo;
349 struct MacEndpoint_id_fragment_triple
351 struct MacEndpoint *endpoint;
353 struct FragmentMessage *fm;
357 struct Plugin_Session_pair
359 struct Plugin *plugin;
360 struct Session *session;
365 * Header for messages which need fragmentation
370 struct GNUNET_MessageHeader header;
373 * checksum/error correction
375 uint32_t crc GNUNET_PACKED;
378 * To whom are we talking to (set to our identity
379 * if we are still waiting for the welcome message)
381 struct GNUNET_PeerIdentity target;
384 * Where the packet came from
386 struct GNUNET_PeerIdentity source;
388 // followed by payload
394 * Information kept for each message that is yet to
397 struct PendingMessage
402 struct PendingMessage *next;
406 struct PendingMessage *prev;
409 * The pending message
411 struct WlanHeader *msg;
414 * Size of the message
419 * Continuation function to call once the message
420 * has been sent. Can be NULL if there is no
421 * continuation to call.
423 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
426 * Cls for transmit_cont
428 void *transmit_cont_cls;
431 * Timeout value for the pending message.
433 struct GNUNET_TIME_Absolute timeout;
438 * Queue for acks to send for fragments recived
444 * next ack in the ack send queue
446 struct AckSendQueue *next;
448 * previous ack in the ack send queue
450 struct AckSendQueue *prev;
452 * pointer to the session this ack belongs to
454 struct MacEndpoint *endpoint;
456 * ID of message, to distinguish between the messages, picked randomly.
463 struct GNUNET_MessageHeader *hdr;
465 * pointer to the ieee wlan header
467 struct ieee80211_frame *ieeewlanheader;
469 * pointer to the radiotap header
471 struct Radiotap_Send *radioHeader;
475 * Session infos gathered from a messages
480 * the session this message belongs to
482 struct Session *session;
486 struct MacAddress addr;
491 struct MacEndpoint *macendpoint;
495 * Session handle for connections.
503 struct SessionHeader header;
506 * Message currently pending for transmission
507 * to this peer, if any. head
509 struct PendingMessage *pending_message_head;
512 * Message currently pending for transmission
513 * to this peer, if any. tail
515 struct PendingMessage *pending_message_tail;
518 * To whom are we talking to (set to our identity
519 * if we are still waiting for the welcome message)
521 struct GNUNET_PeerIdentity target;
524 * Address of the other peer (either based on our 'connect'
525 * call or on our 'accept' call).
530 * Last activity on this connection. Used to select preferred
531 * connection and timeout
533 struct GNUNET_TIME_Absolute last_activity;
538 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
543 struct MacEndpoint *mac;
546 * count of messages in the fragment out queue for this session
549 int fragment_messages_out_count;
554 * Struct to represent one network card connection
559 * Pointer to the global plugin struct.
561 struct Plugin *plugin;
563 * Struct to hold the session reachable over this mac; head
565 struct Sessionqueue *sessions_head;
567 * Struct to hold the session reachable over this mac; tail
569 struct Sessionqueue *sessions_tail;
571 * Messages currently sending
574 struct FragmentMessage *sending_messages_head;
577 * Messages currently sending
578 * to a peer (tail), if any.
580 struct FragmentMessage *sending_messages_tail;
584 struct MacEndpoint *next;
588 struct MacEndpoint *prev;
593 struct MacAddress addr;
596 * Defrag context for this mac endpoint
598 struct GNUNET_DEFRAGMENT_Context *defrag;
601 * count of messages in the fragment out queue for this mac endpoint
604 int fragment_messages_out_count;
612 * Duplicates received
627 * Last activity on this endpoint. Used to select preferred
630 struct GNUNET_TIME_Absolute last_activity;
635 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
639 * Struct for Messages in the fragment queue
641 struct FragmentMessage
645 * Session this message belongs to
647 struct Session *session;
650 * This is a doubly-linked list.
652 struct FragmentMessage *next;
655 * This is a doubly-linked list.
657 struct FragmentMessage *prev;
660 * Fragmentation context
662 struct GNUNET_FRAGMENT_Context *fragcontext;
665 * Timeout value for the message.
667 struct GNUNET_TIME_Absolute timeout;
672 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
685 * pointer to the ieee wlan header
687 struct ieee80211_frame *ieeewlanheader;
689 * pointer to the radiotap header
691 struct Radiotap_Send *radioHeader;
695 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
698 free_session (struct Plugin *plugin, struct Sessionqueue *queue,
699 int do_free_macendpoint);
701 static struct MacEndpoint *
702 create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr);
705 finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
708 * Generates a nice hexdump of a memory area.
710 * \param mem pointer to memory to dump
711 * \param length how many bytes to dump
714 hexdump (const void *mem, unsigned length)
717 char *src = (char *) mem;
719 printf ("dumping %u bytes from %p\r\n"
720 " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\r\n",
725 for (i = 0; i < length; i += 16, src += 16)
729 t += sprintf (t, "%04x: ", i);
730 for (j = 0; j < 16; j++)
733 t += sprintf (t, "%02X", src[j] & 0xff);
735 t += sprintf (t, " ");
737 t += sprintf (t, j % 2 ? " " : "-");
740 t += sprintf (t, " ");
741 for (j = 0; j < 16; j++)
745 if (isprint ((unsigned char) src[j]))
746 t += sprintf (t, "%c", src[j]);
748 t += sprintf (t, ".");
752 t += sprintf (t, " ");
756 t += sprintf (t, "\r\n");
762 * Function to find a MacEndpoint with a specific mac addr
763 * @param plugin pointer to the plugin struct
764 * @param addr pointer to the mac address
765 * @param create_new GNUNET_YES if a new end point should be created
768 static struct MacEndpoint *
769 get_macendpoint (struct Plugin *plugin, const struct MacAddress *addr,
772 struct MacEndpoint *queue = plugin->mac_head;
774 while (queue != NULL)
776 //GNUNET_assert (queue->sessions_head != NULL);
777 if (memcmp (addr, &queue->addr, sizeof (struct MacAddress)) == 0)
778 return queue; /* session found */
782 if (create_new == GNUNET_YES)
784 return create_macendpoint (plugin, addr);
794 * search for a session with the macendpoint and peer id
796 * @param plugin pointer to the plugin struct
797 * @param endpoint pointer to the mac endpoint of the peer
798 * @param peer pointer to the peerid
799 * @return returns the session
801 static struct Session *
802 search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
803 const struct GNUNET_PeerIdentity *peer)
805 GNUNET_assert (endpoint != NULL);
806 struct Sessionqueue *queue = endpoint->sessions_head;
808 while (queue != NULL)
810 GNUNET_assert (queue->content != NULL);
812 (peer, &queue->content->target,
813 sizeof (struct GNUNET_PeerIdentity)) == 0)
814 return queue->content; /* session found */
821 * Function called for a quick conversion of the binary address to
822 * a numeric address. Note that the caller must not free the
823 * address and that the next call to this function is allowed
824 * to override the address again.
827 * @param addr binary address
828 * @param addrlen length of the address
829 * @return string representing the same address
832 wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
835 const struct MacAddress *mac;
837 if (addrlen != sizeof (struct MacAddress))
843 GNUNET_snprintf (ret, sizeof (ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
844 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2],
845 mac->mac[3], mac->mac[4], mac->mac[5]);
851 * Function for the scheduler if a session times out
852 * @param cls pointer to the Sessionqueue
853 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
856 session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
858 struct Sessionqueue *queue = cls;
860 GNUNET_assert (queue != NULL);
861 GNUNET_assert (queue->content != NULL);
862 queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
863 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
867 if (GNUNET_TIME_absolute_get_remaining
868 (GNUNET_TIME_absolute_add
869 (queue->content->last_activity, SESSION_TIMEOUT)).rel_value == 0)
872 GNUNET_assert (queue->content->mac != NULL);
873 GNUNET_assert (queue->content->mac->plugin != NULL);
874 GNUNET_STATISTICS_update (queue->content->mac->plugin->env->stats,
875 _("# wlan session timeouts"), 1, GNUNET_NO);
876 free_session (queue->content->mac->plugin, queue, GNUNET_YES);
880 queue->content->timeout_task =
881 GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
886 * create a new session
888 * @param plugin pointer to the plugin struct
889 * @param endpoint pointer to the mac endpoint of the peer
890 * @param peer peer identity to use for this session
891 * @return returns the session
893 static struct Session *
894 create_session (struct Plugin *plugin, struct MacEndpoint *endpoint,
895 const struct GNUNET_PeerIdentity *peer)
897 GNUNET_assert (endpoint != NULL);
898 GNUNET_assert (plugin != NULL);
899 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan session created"), 1,
901 struct Sessionqueue *queue =
902 GNUNET_malloc (sizeof (struct Sessionqueue) + sizeof (struct Session));
904 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
905 endpoint->sessions_tail, queue);
907 queue->content = (struct Session *) &queue[1];
908 queue->content->mac = endpoint;
909 queue->content->target = *peer;
910 queue->content->last_activity = GNUNET_TIME_absolute_get ();
911 queue->content->timeout_task =
912 GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
915 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
916 "New session %p with endpoint %p: %s\n", queue->content,
917 endpoint, wlan_plugin_address_to_string (NULL,
922 return queue->content;
926 * Get session from address, create if no session exists
928 * @param plugin pointer to the plugin struct
929 * @param addr pointer to the mac address of the peer
930 * @param peer pointer to the peerid
931 * @return returns the session
933 static struct Session *
934 get_session (struct Plugin *plugin, const struct MacAddress *addr,
935 const struct GNUNET_PeerIdentity *peer)
937 struct MacEndpoint *mac;
939 mac = get_macendpoint (plugin, addr, GNUNET_YES);
940 struct Session *session = search_session (plugin, mac, peer);
944 return create_session (plugin, mac, peer);
948 * Queue the session to send data
949 * checks if there is a message pending
950 * checks if this session is not allready in the queue
951 * @param plugin pointer to the plugin
952 * @param session pointer to the session to add
955 queue_session (struct Plugin *plugin, struct Session *session)
957 struct Sessionqueue *queue = plugin->pending_Sessions_head;
959 if (session->pending_message_head != NULL)
961 while (queue != NULL)
963 // content is never NULL
964 GNUNET_assert (queue->content != NULL);
965 // is session already in queue?
966 if (session == queue->content)
974 // Session is not in the queue
976 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
977 queue->content = session;
980 GNUNET_CONTAINER_DLL_insert_tail (plugin->pending_Sessions_head,
981 plugin->pending_Sessions_tail, queue);
982 plugin->pendingsessions++;
983 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
984 plugin->pendingsessions, GNUNET_NO);
990 * Function to schedule the write task, executed after a delay
991 * @param cls pointer to the plugin struct
992 * @param tc GNUNET_SCHEDULER_TaskContext pointer
995 delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
997 struct Plugin *plugin = cls;
999 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1001 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1004 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
1005 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1007 plugin->server_write_task =
1008 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1009 plugin->server_stdin_handle,
1010 &do_transmit, plugin);
1015 * Function to calculate the time of the next periodic "hello-beacon"
1016 * @param plugin pointer to the plugin struct
1019 set_next_beacon_time (struct Plugin *const plugin)
1021 //under 10 known peers: once a second
1022 if (plugin->mac_count < 10)
1024 plugin->beacon_time =
1025 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1026 GNUNET_TIME_relative_multiply
1027 (GNUNET_TIME_UNIT_SECONDS,
1028 HELLO_BEACON_SCALING_FACTOR));
1030 //under 30 known peers: every 10 seconds
1031 else if (plugin->mac_count < 30)
1033 plugin->beacon_time =
1034 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1035 GNUNET_TIME_relative_multiply
1036 (GNUNET_TIME_UNIT_SECONDS,
1037 10 * HELLO_BEACON_SCALING_FACTOR));
1039 //over 30 known peers: once a minute
1042 plugin->beacon_time =
1043 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1044 GNUNET_TIME_relative_multiply
1045 (GNUNET_TIME_UNIT_MINUTES,
1046 HELLO_BEACON_SCALING_FACTOR));
1051 * Function to set the timer for the next timeout of the fragment queue
1052 * @param plugin the handle to the plugin struct
1055 set_next_send (struct Plugin *const plugin)
1057 struct GNUNET_TIME_Relative next_send;
1059 //abort if helper is not running
1060 if (plugin->helper_is_running == GNUNET_NO)
1066 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1068 GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
1069 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1072 //check if some acks are in the queue
1073 if (plugin->ack_send_queue_head != NULL)
1075 next_send = GNUNET_TIME_UNIT_ZERO;
1078 //check if there are some fragments in the queue
1079 else if (plugin->sending_messages_head != NULL)
1081 next_send = GNUNET_TIME_UNIT_ZERO;
1085 next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
1089 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1090 "Next packet is send in: %u\n", next_send.rel_value);
1093 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
1095 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1097 plugin->server_write_task =
1098 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1099 plugin->server_stdin_handle,
1100 &do_transmit, plugin);
1105 if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
1107 plugin->server_write_delay_task =
1108 GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
1115 * Function to get the next queued Session, removes the session from the queue
1116 * @param plugin pointer to the plugin struct
1117 * @return pointer to the session found, returns NULL if there is now session in the queue
1119 static struct Session *
1120 get_next_queue_session (struct Plugin *plugin)
1122 struct Session *session;
1123 struct Sessionqueue *sessionqueue;
1124 struct Sessionqueue *sessionqueue_alt;
1125 struct PendingMessage *pm;
1127 sessionqueue = plugin->pending_Sessions_head;
1129 while (sessionqueue != NULL)
1131 session = sessionqueue->content;
1133 GNUNET_assert (session != NULL);
1134 pm = session->pending_message_head;
1139 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1140 "pending message is empty, should not happen. session %p\n",
1143 sessionqueue_alt = sessionqueue;
1144 sessionqueue = sessionqueue->next;
1145 plugin->pendingsessions--;
1146 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1147 plugin->pendingsessions, GNUNET_NO);
1148 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1149 plugin->pending_Sessions_tail,
1152 GNUNET_free (sessionqueue_alt);
1157 //check for message timeout
1158 if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
1160 //check if session has no message in the fragment queue
1161 if ((session->mac->fragment_messages_out_count <
1162 FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
1163 (session->fragment_messages_out_count <
1164 FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
1166 plugin->pendingsessions--;
1167 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1168 plugin->pendingsessions, GNUNET_NO);
1169 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1170 plugin->pending_Sessions_tail,
1172 GNUNET_free (sessionqueue);
1178 sessionqueue = sessionqueue->next;
1183 GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1184 session->pending_message_tail, pm);
1186 //call the cont func that it did not work
1187 if (pm->transmit_cont != NULL)
1188 pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
1190 GNUNET_free (pm->msg);
1193 if (session->pending_message_head == NULL)
1195 sessionqueue_alt = sessionqueue;
1196 sessionqueue = sessionqueue->next;
1197 plugin->pendingsessions--;
1198 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1199 plugin->pendingsessions, GNUNET_NO);
1200 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1201 plugin->pending_Sessions_tail,
1204 GNUNET_free (sessionqueue_alt);
1213 * frees the space of a message in the fragment queue (send queue)
1214 * @param plugin the plugin struct
1215 * @param fm message to free
1218 free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
1220 struct Session *session = fm->session;
1221 struct MacEndpoint *endpoint = session->mac;
1222 struct FragmentMessage_queue *fmq;
1223 struct FragmentMessage_queue *fmq_next;
1225 fmq = plugin->sending_messages_head;
1228 fmq_next = fmq->next;
1229 if (fmq->content == fm)
1231 GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
1232 plugin->sending_messages_tail, fmq);
1238 (session->mac->fragment_messages_out_count)--;
1239 session->fragment_messages_out_count--;
1240 plugin->pending_Fragment_Messages--;
1241 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1242 plugin->pending_Fragment_Messages, GNUNET_NO);
1243 GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
1244 endpoint->sending_messages_tail, fm);
1245 GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
1246 if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1248 GNUNET_SCHEDULER_cancel (fm->timeout_task);
1249 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1254 queue_session (plugin, session);
1256 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1257 "Free pending fragment messages %p, session %p\n", fm,
1263 * function to fill the radiotap header
1264 * @param plugin pointer to the plugin struct
1265 * @param endpoint pointer to the endpoint
1266 * @param header pointer to the radiotap header
1267 * @return GNUNET_YES at success
1270 getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
1271 struct Radiotap_Send *header)
1274 if (endpoint != NULL)
1276 header->rate = endpoint->rate;
1277 header->tx_power = endpoint->tx_power;
1278 header->antenna = endpoint->antenna;
1283 header->tx_power = 0;
1284 header->antenna = 0;
1291 * function to generate the wlan hardware header for one packet
1292 * @param Header address to write the header to
1293 * @param to_mac_addr address of the recipient
1294 * @param plugin pointer to the plugin struct
1295 * @param size size of the whole packet, needed to calculate the time to send the packet
1296 * @return GNUNET_YES if there was no error
1299 getWlanHeader (struct ieee80211_frame *Header,
1300 const struct MacAddress *to_mac_addr, struct Plugin *plugin,
1304 const int rate = 11000000;
1306 Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
1307 Header->i_fc[1] = 0x00;
1308 memcpy (&Header->i_addr3, &mac_bssid_gnunet, sizeof (mac_bssid_gnunet));
1309 memcpy (&Header->i_addr2, plugin->mac_address.mac,
1310 sizeof (plugin->mac_address));
1311 memcpy (&Header->i_addr1, to_mac_addr, sizeof (struct MacAddress));
1313 tmp16 = (uint16_t *) Header->i_dur;
1314 *tmp16 = (uint16_t) GNUNET_htole16 ((size * 1000000) / rate + 290);
1315 Header->llc[0] = WLAN_LLC_DSAP_FIELD;
1316 Header->llc[1] = WLAN_LLC_SSAP_FIELD;
1323 * function to add a fragment of a message to send
1324 * @param cls FragmentMessage this message belongs to
1325 * @param hdr pointer to the start of the message
1328 add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
1331 struct FragmentMessage *fm = cls;
1332 struct FragmentMessage_queue *fmqueue;
1334 GNUNET_assert (cls != NULL);
1335 GNUNET_assert (fm->frag == NULL);
1336 struct MacEndpoint *endpoint = fm->session->mac;
1337 struct Plugin *plugin = endpoint->plugin;
1338 struct GNUNET_MessageHeader *msgheader;
1339 struct GNUNET_MessageHeader *msgheader2;
1342 #if DEBUG_wlan_retransmission > 1
1343 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1344 "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
1345 fm, fm->session, endpoint, hdr->type);
1349 sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1350 sizeof (struct ieee80211_frame) + ntohs (hdr->size);
1351 fm->frag = GNUNET_malloc (size);
1354 msgheader = (struct GNUNET_MessageHeader *) fm->frag;
1355 msgheader->size = htons (size);
1356 msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1358 fm->radioHeader = (struct Radiotap_Send *) &msgheader[1];
1359 fm->ieeewlanheader = (struct ieee80211_frame *) &fm->radioHeader[1];
1360 msgheader2 = (struct GNUNET_MessageHeader *) &fm->ieeewlanheader[1];
1361 memcpy (msgheader2, hdr, ntohs (hdr->size));
1363 fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
1364 fmqueue->content = fm;
1366 GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
1367 plugin->sending_messages_tail, fmqueue);
1368 set_next_send (plugin);
1373 * We have been notified that gnunet-helper-transport-wlan has written something to stdout.
1374 * Handle the output, then reschedule this function to be called again once
1375 * more is available.
1377 * @param cls the plugin handle
1378 * @param tc the scheduling context
1381 wlan_plugin_helper_read (void *cls,
1382 const struct GNUNET_SCHEDULER_TaskContext *tc)
1384 struct Plugin *plugin = cls;
1386 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1388 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1391 char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
1395 GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf,
1400 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1402 ("Finished reading from gnunet-helper-transport-wlan stdout with code: %d\n"),
1407 GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
1408 GNUNET_NO, GNUNET_NO);
1410 GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1411 plugin->server_read_task =
1412 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1413 plugin->server_stdout_handle,
1414 &wlan_plugin_helper_read, plugin);
1418 * Start the gnunet-helper-transport-wlan process.
1420 * @param plugin the transport plugin
1421 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1424 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1426 const char *filenamehw = "gnunet-helper-transport-wlan";
1427 const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
1428 char *absolute_filename = NULL;
1430 if (plugin->helper_is_running == GNUNET_YES)
1433 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1434 "wlan_transport_start_wlan_helper not needed, helper already running!");
1439 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1440 if (plugin->server_stdout == NULL)
1441 return GNUNET_SYSERR;
1443 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1444 if (plugin->server_stdin == NULL)
1445 return GNUNET_SYSERR;
1447 if ((plugin->testmode == 1) || (plugin->testmode == 2))
1449 if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
1451 absolute_filename = GNUNET_strdup (filenameloopback);
1455 char cwd[FILENAME_MAX];
1457 GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
1459 GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
1462 if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
1464 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1465 "Helper `%s' not found! %i\n", absolute_filename);
1471 /* Start the server process */
1473 if (plugin->testmode == 0)
1477 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1478 "Starting gnunet-helper-transport-wlan process cmd: %s %s %i\n",
1479 filenamehw, plugin->interface, plugin->testmode);
1482 if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
1484 plugin->server_proc =
1485 GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1486 filenamehw, filenamehw, plugin->interface,
1489 else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO)
1491 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1492 "gnunet-helper-transport-wlan is not suid, please change it or look at the doku\n");
1497 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1498 "gnunet-helper-transport-wlan not found, please look if it exists and is the $PATH variable!\n");
1503 else if (plugin->testmode == 1)
1507 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1508 "Starting gnunet-helper-transport-wlan-dummy loopback 1 process cmd: %s %s %i\n",
1509 absolute_filename, plugin->interface, plugin->testmode);
1511 plugin->server_proc =
1512 GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1513 absolute_filename, absolute_filename, "1",
1515 if (plugin->server_proc == NULL)
1517 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1518 "`%s' not found, please look if it exists and is in the $PATH variable!\n",
1523 else if (plugin->testmode == 2)
1526 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1527 "Starting gnunet-helper-transport-wlan-dummy loopback 2 process cmd: %s %s %i\n",
1528 absolute_filename, plugin->interface, plugin->testmode);
1531 plugin->server_proc =
1532 GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1533 absolute_filename, absolute_filename, "2",
1535 if (plugin->server_proc == NULL)
1537 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1538 "`%s' not found, please look if it exists and is in the $PATH variable!\n",
1543 if (absolute_filename != NULL)
1544 GNUNET_free (absolute_filename);
1545 if (plugin->server_proc == NULL)
1548 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1549 "Failed to start gnunet-helper-transport-wlan process\n");
1551 return GNUNET_SYSERR;
1556 /* Close the write end of the read pipe */
1557 GNUNET_DISK_pipe_close_end (plugin->server_stdout,
1558 GNUNET_DISK_PIPE_END_WRITE);
1560 /* Close the read end of the write pipe */
1561 GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1563 plugin->server_stdout_handle =
1564 GNUNET_DISK_pipe_handle (plugin->server_stdout,
1565 GNUNET_DISK_PIPE_END_READ);
1566 plugin->server_stdin_handle =
1567 GNUNET_DISK_pipe_handle (plugin->server_stdin,
1568 GNUNET_DISK_PIPE_END_WRITE);
1570 GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1573 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1574 "Adding server_read_task for the gnunet-helper-transport-wlan\n");
1577 plugin->server_read_task =
1578 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1579 plugin->server_stdout_handle,
1580 &wlan_plugin_helper_read, plugin);
1582 plugin->helper_is_running = GNUNET_YES;
1587 * Stops the gnunet-helper-transport-wlan process.
1589 * @param plugin the transport plugin
1590 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1593 wlan_transport_stop_wlan_helper (struct Plugin *plugin)
1596 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1597 "Stoping WLAN helper process\n");
1600 if (plugin->helper_is_running == GNUNET_NO)
1603 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1604 "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
1609 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1611 GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
1612 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1615 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
1617 GNUNET_SCHEDULER_cancel (plugin->server_write_task);
1618 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1621 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
1623 GNUNET_SCHEDULER_cancel (plugin->server_read_task);
1624 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1627 GNUNET_DISK_pipe_close (plugin->server_stdout);
1628 GNUNET_DISK_pipe_close (plugin->server_stdin);
1629 GNUNET_OS_process_kill (plugin->server_proc, SIGKILL);
1630 GNUNET_OS_process_wait (plugin->server_proc);
1631 GNUNET_OS_process_close (plugin->server_proc);
1633 plugin->helper_is_running = GNUNET_NO;
1639 * function for delayed restart of the helper process
1640 * @param cls Finish_send struct if message should be finished
1641 * @param tc TaskContext
1644 delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1646 struct Finish_send *finish = cls;
1647 struct Plugin *plugin;
1649 plugin = finish->plugin;
1651 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1652 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1654 GNUNET_free_non_null (finish->msgstart);
1655 GNUNET_free (finish);
1659 wlan_transport_start_wlan_helper (plugin);
1661 if (finish->size != 0)
1663 plugin->server_write_task =
1664 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1665 plugin->server_stdin_handle,
1666 &finish_sending, finish);
1670 set_next_send (plugin);
1671 GNUNET_free_non_null (finish->msgstart);
1672 GNUNET_free (finish);
1678 * Function to restart the helper
1679 * @param plugin pointer to the global plugin struct
1680 * @param finish pointer to the Finish_send struct to finish
1683 restart_helper (struct Plugin *plugin, struct Finish_send *finish)
1685 static struct GNUNET_TIME_Relative next_try = { 1000 };
1686 GNUNET_assert (finish != NULL);
1688 wlan_transport_stop_wlan_helper (plugin);
1689 plugin->server_write_task =
1690 GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish);
1691 GNUNET_TIME_relative_multiply (next_try, HELPER_RESTART_SCALING_FACTOR);
1696 * function to finish a sending if not all could have been writen befor
1697 * @param cls pointer to the Finish_send struct
1698 * @param tc TaskContext
1701 finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1703 struct Finish_send *finish = cls;
1704 struct Plugin *plugin;
1707 plugin = finish->plugin;
1708 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1710 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1712 GNUNET_free (finish->msgstart);
1713 GNUNET_free (finish);
1717 GNUNET_DISK_file_write (plugin->server_stdin_handle,
1718 finish->head_of_next_write, finish->size);
1720 if (bytes != finish->size)
1722 if (bytes != GNUNET_SYSERR)
1724 finish->head_of_next_write += bytes;
1725 finish->size -= bytes;
1726 plugin->server_write_task =
1727 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1728 plugin->server_stdin_handle,
1729 &finish_sending, finish);
1733 restart_helper (plugin, finish);
1738 GNUNET_free (finish->msgstart);
1739 GNUNET_free (finish);
1740 set_next_send (plugin);
1745 * function to send a hello beacon
1746 * @param plugin pointer to the plugin struct
1749 send_hello_beacon (struct Plugin *plugin)
1753 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1754 "Sending hello beacon\n");
1759 uint16_t hello_size;
1760 struct GNUNET_MessageHeader *msgheader;
1761 struct ieee80211_frame *ieeewlanheader;
1762 struct Radiotap_Send *radioHeader;
1763 struct GNUNET_MessageHeader *msgheader2;
1764 const struct GNUNET_MessageHeader *hello;
1765 struct Finish_send *finish;
1767 GNUNET_assert (plugin != NULL);
1769 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"),
1772 hello = plugin->env->get_our_hello ();
1773 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1774 GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1776 sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1777 sizeof (struct ieee80211_frame) + hello_size;
1779 msgheader = GNUNET_malloc (size);
1780 msgheader->size = htons (size);
1781 msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1783 radioHeader = (struct Radiotap_Send *) &msgheader[1];
1784 getRadiotapHeader (plugin, NULL, radioHeader);
1785 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1786 getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size);
1788 msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1789 /*msgheader2->size =
1790 * htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) +
1791 * sizeof (struct GNUNET_MessageHeader));
1793 * msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); */
1794 memcpy (msgheader2, hello, hello_size);
1796 bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size);
1798 if (bytes == GNUNET_SYSERR)
1800 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1802 ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
1803 errno, strerror (errno));
1804 finish = GNUNET_malloc (sizeof (struct Finish_send));
1805 finish->plugin = plugin;
1806 finish->head_of_next_write = NULL;
1808 finish->msgstart = NULL;
1809 restart_helper (plugin, finish);
1811 set_next_beacon_time (plugin);
1816 GNUNET_assert (bytes == size);
1817 set_next_beacon_time (plugin);
1818 set_next_send (plugin);
1820 GNUNET_free (msgheader);
1826 * function to add an ack to send it for a received fragment
1827 * @param cls MacEndpoint this ack belongs to
1828 * @param msg_id id of the message
1829 * @param hdr pointer to the hdr where the ack is stored
1833 add_ack_for_send (void *cls, uint32_t msg_id,
1834 const struct GNUNET_MessageHeader *hdr)
1837 struct AckSendQueue *ack;
1839 GNUNET_assert (cls != NULL);
1840 struct MacEndpoint *endpoint = cls;
1841 struct Plugin *plugin = endpoint->plugin;
1842 struct GNUNET_MessageHeader *msgheader;
1843 struct GNUNET_MessageHeader *msgheader2;
1847 sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1848 sizeof (struct ieee80211_frame) + ntohs (hdr->size) +
1849 sizeof (struct AckSendQueue);
1851 ack = GNUNET_malloc (size);
1852 ack->message_id = msg_id;
1853 ack->endpoint = endpoint;
1856 sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1857 sizeof (struct ieee80211_frame) + ntohs (hdr->size);
1859 msgheader = (struct GNUNET_MessageHeader *) &ack[1];
1860 ack->hdr = (struct GNUNET_MessageHeader *) &ack[1];
1861 msgheader->size = htons (size);
1862 msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1864 ack->radioHeader = (struct Radiotap_Send *) &msgheader[1];
1865 ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1];
1866 msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1];
1867 memcpy (msgheader2, hdr, ntohs (hdr->size));
1869 GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
1870 plugin->ack_send_queue_tail, ack);
1872 #if DEBUG_wlan_retransmission > 1
1873 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1874 "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
1875 msg_id, ack, endpoint);
1878 set_next_send (plugin);
1882 * Function for the scheduler if a FragmentMessage times out
1883 * @param cls pointer to the FragmentMessage
1884 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1887 fragmentmessage_timeout (void *cls,
1888 const struct GNUNET_SCHEDULER_TaskContext *tc)
1890 struct FragmentMessage *fm = cls;
1892 GNUNET_assert (fm != NULL);
1893 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1894 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1898 free_fragment_message (fm->session->mac->plugin, fm);
1902 * Function to check if there is some space in the fragment queue
1903 * inserts a message if space is available
1904 * @param plugin the plugin struct
1908 check_fragment_queue (struct Plugin *plugin)
1910 struct Session *session;
1911 struct FragmentMessage *fm;
1912 struct GNUNET_PeerIdentity pid;
1914 struct PendingMessage *pm;
1916 if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
1918 session = get_next_queue_session (plugin);
1919 if (session != NULL)
1921 pm = session->pending_message_head;
1922 GNUNET_assert (pm != NULL);
1923 GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1924 session->pending_message_tail, pm);
1925 session->mac->fragment_messages_out_count++;
1926 session->fragment_messages_out_count++;
1927 plugin->pending_Fragment_Messages++;
1928 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1929 plugin->pending_Fragment_Messages, GNUNET_NO);
1931 fm = GNUNET_malloc (sizeof (struct FragmentMessage));
1932 fm->session = session;
1933 fm->timeout.abs_value = pm->timeout.abs_value;
1936 GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
1938 GNUNET_TIME_UNIT_SECONDS,
1940 &add_message_for_send, fm);
1942 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
1943 (fm->timeout), fragmentmessage_timeout,
1945 GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
1946 session->mac->sending_messages_tail,
1949 if (pm->transmit_cont != NULL)
1951 pid = session->target;
1952 pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
1954 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1955 "called pm->transmit_cont for %p\n", session);
1961 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1962 "no pm->transmit_cont for %p\n", session);
1967 if (session->pending_message_head != NULL)
1970 queue_session (plugin, session);
1976 //check if timeout changed
1977 set_next_send (plugin);
1981 * Function to send an ack, does not free the ack
1982 * @param plugin pointer to the plugin
1985 send_ack (struct Plugin *plugin)
1989 struct AckSendQueue *ack;
1990 struct Finish_send *finish;
1992 ack = plugin->ack_send_queue_head;
1996 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1997 "Sending ack for message_id %u for mac endpoint %p, size %u\n",
1998 ack->message_id, ack->endpoint,
1999 ntohs (ack->hdr->size) - sizeof (struct Radiotap_Send));
2002 GNUNET_assert (plugin != NULL);
2003 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
2006 getRadiotapHeader (plugin, ack->endpoint, ack->radioHeader);
2007 getWlanHeader (ack->ieeewlanheader, &ack->endpoint->addr, plugin,
2008 ntohs (ack->hdr->size));
2011 GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
2012 ntohs (ack->hdr->size));
2013 if (bytes == GNUNET_SYSERR)
2015 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2017 ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
2018 errno, strerror (errno));
2019 finish = GNUNET_malloc (sizeof (struct Finish_send));
2020 finish->plugin = plugin;
2021 finish->head_of_next_write = NULL;
2023 finish->msgstart = NULL;
2024 restart_helper (plugin, finish);
2028 GNUNET_assert (bytes == ntohs (ack->hdr->size));
2029 GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
2030 plugin->ack_send_queue_tail, ack);
2032 set_next_send (plugin);
2037 * Function called when wlan helper is ready to get some data
2039 * @param cls closure
2040 * @param tc GNUNET_SCHEDULER_TaskContext
2043 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2045 struct Plugin *plugin = cls;
2047 GNUNET_assert (plugin != NULL);
2049 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2050 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2053 struct Session *session;
2054 struct FragmentMessage *fm;
2055 struct Finish_send *finish;
2056 struct FragmentMessage_queue *fmq;
2059 if (plugin->ack_send_queue_head != NULL)
2065 //test if a "hello-beacon" has to be send
2066 if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
2068 send_hello_beacon (plugin);
2072 if (plugin->sending_messages_head != NULL)
2074 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan fragments send"), 1,
2077 fmq = plugin->sending_messages_head;
2079 GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
2080 plugin->sending_messages_tail, fmq);
2083 session = fm->session;
2084 GNUNET_assert (session != NULL);
2087 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2088 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
2092 getRadiotapHeader (plugin, session->mac, fm->radioHeader);
2093 getWlanHeader (fm->ieeewlanheader, &(fm->session->mac->addr), plugin,
2097 GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
2101 if (bytes != fm->size)
2103 finish = GNUNET_malloc (sizeof (struct Finish_send));
2104 finish->plugin = plugin;
2105 finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag;
2106 GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
2108 if (bytes == GNUNET_SYSERR)
2110 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2112 ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
2113 errno, strerror (errno));
2115 finish->head_of_next_write = fm->frag;
2116 finish->size = fm->size;
2117 restart_helper (plugin, finish);
2121 finish->head_of_next_write = fm->frag + bytes;
2122 finish->size = fm->size - bytes;
2123 plugin->server_write_task =
2124 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
2125 plugin->server_stdin_handle,
2126 &finish_sending, finish);
2133 GNUNET_free (fm->frag);
2135 set_next_send (plugin);
2137 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
2142 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2143 "do_transmit did nothing, should not happen!\n");
2145 set_next_send (plugin);
2149 * Another peer has suggested an address for this
2150 * peer and transport plugin. Check that this could be a valid
2151 * address. If so, consider adding it to the list
2154 * @param cls closure
2155 * @param addr pointer to the address
2156 * @param addrlen length of addr
2157 * @return GNUNET_OK if this is a plausible address for this peer
2161 wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
2163 //struct Plugin *plugin = cls;
2165 /* check if the address is plausible; if so,
2166 * add it to our list! */
2168 GNUNET_assert (cls != NULL);
2169 //FIXME mitm is not checked
2170 //Mac Address has 6 bytes
2173 /* TODO check for bad addresses like multicast, broadcast, etc */
2175 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2176 "wlan_plugin_address_suggested got good address, size %u!\n",
2182 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2183 "wlan_plugin_address_suggested got bad address, size %u!\n",
2186 return GNUNET_SYSERR;
2190 * Function that can be used by the transport service to transmit
2191 * a message using the plugin.
2193 * @param cls closure
2194 * @param target who should receive this message
2195 * @param priority how important is the message
2196 * @param msgbuf the message to transmit
2197 * @param msgbuf_size number of bytes in 'msgbuf'
2198 * @param timeout when should we time out
2199 * @param session which session must be used (or NULL for "any")
2200 * @param addr the address to use (can be NULL if the plugin
2201 * is "on its own" (i.e. re-use existing TCP connection))
2202 * @param addrlen length of the address in bytes
2203 * @param force_address GNUNET_YES if the plugin MUST use the given address,
2204 * otherwise the plugin may use other addresses or
2205 * existing connections (if available)
2206 * @param cont continuation to call once the message has
2207 * been transmitted (or if the transport is ready
2208 * for the next transmission call; or if the
2209 * peer disconnected...)
2210 * @param cont_cls closure for cont
2211 * @return number of bytes used (on the physical network, with overheads);
2212 * -1 on hard errors (i.e. address invalid); 0 is a legal value
2213 * and does NOT mean that the message was not transmitted (DV)
2216 wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
2217 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
2218 struct GNUNET_TIME_Relative timeout, struct Session *session,
2219 const void *addr, size_t addrlen, int force_address,
2220 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
2222 struct Plugin *plugin = cls;
2223 struct PendingMessage *newmsg;
2224 struct WlanHeader *wlanheader;
2226 GNUNET_assert (plugin != NULL);
2227 //check if msglen > 0
2228 GNUNET_assert (msgbuf_size > 0);
2230 //get session if needed
2231 if (session == NULL)
2233 if (wlan_plugin_address_suggested (plugin, addr, addrlen) == GNUNET_OK)
2235 session = get_session (plugin, addr, target);
2239 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2240 _("Wlan Address len %d is wrong\n"), addrlen);
2245 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan messages queued"), 1,
2250 //queue message in session
2251 //test if there is no other message in the "queue"
2252 //FIXME: to many send requests
2253 if (session->pending_message_head != NULL)
2255 newmsg = session->pending_message_head;
2256 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2257 "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 for this mac connection %u\n",
2258 GNUNET_TIME_absolute_get_remaining (newmsg->
2260 session->mac->fragment_messages_out_count);
2263 newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
2264 newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
2265 wlanheader = newmsg->msg;
2266 //copy msg to buffer, not fragmented / segmented yet, but with message header
2267 wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
2268 wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
2269 memcpy (&(wlanheader->target), target, sizeof (struct GNUNET_PeerIdentity));
2270 memcpy (&(wlanheader->source), plugin->env->my_identity,
2271 sizeof (struct GNUNET_PeerIdentity));
2272 wlanheader->crc = 0;
2273 memcpy (&wlanheader[1], msgbuf, msgbuf_size);
2275 htonl (GNUNET_CRYPTO_crc32_n
2276 ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
2278 newmsg->transmit_cont = cont;
2279 newmsg->transmit_cont_cls = cont_cls;
2280 newmsg->timeout = GNUNET_TIME_relative_to_absolute (timeout);
2282 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
2284 newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
2286 GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
2287 session->pending_message_tail, newmsg);
2290 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2291 "New message for %p with size (incl wlan header) %u added\n",
2292 session, newmsg->message_size);
2294 #if DEBUG_wlan_msg_dump > 1
2295 hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
2298 queue_session (plugin, session);
2300 check_fragment_queue (plugin);
2301 //FIXME not the correct size
2307 * function to free a mac endpoint
2308 * @param plugin pointer to the plugin struct
2309 * @param endpoint pointer to the MacEndpoint to free
2312 free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
2314 struct Sessionqueue *sessions;
2315 struct Sessionqueue *sessions_next;
2317 GNUNET_assert (endpoint != NULL);
2319 sessions = endpoint->sessions_head;
2320 while (sessions != NULL)
2322 sessions_next = sessions->next;
2323 free_session (plugin, sessions, GNUNET_NO);
2324 sessions = sessions_next;
2327 GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
2328 if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2330 GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
2331 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2333 plugin->mac_count--;
2334 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2335 plugin->mac_count, GNUNET_NO);
2336 GNUNET_free (endpoint);
2341 * function to free a session
2342 * @param plugin pointer to the plugin
2343 * @param queue pointer to the sessionqueue element to free
2344 * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
2347 free_session (struct Plugin *plugin, struct Sessionqueue *queue,
2348 int do_free_macendpoint)
2350 struct Sessionqueue *pendingsession;
2351 struct Sessionqueue *pendingsession_tmp;
2352 struct PendingMessage *pm;
2353 struct MacEndpoint *endpoint;
2354 struct FragmentMessage *fm;
2355 struct FragmentMessage *fmnext;
2358 GNUNET_assert (plugin != NULL);
2359 GNUNET_assert (queue != NULL);
2360 GNUNET_assert (queue->content != NULL);
2363 //is this session pending for send
2364 pendingsession = plugin->pending_Sessions_head;
2365 while (pendingsession != NULL)
2367 pendingsession_tmp = pendingsession;
2368 pendingsession = pendingsession->next;
2369 GNUNET_assert (pendingsession_tmp->content != NULL);
2370 if (pendingsession_tmp->content == queue->content)
2372 plugin->pendingsessions--;
2373 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
2374 plugin->pendingsessions, GNUNET_NO);
2375 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2376 plugin->pending_Sessions_tail,
2377 pendingsession_tmp);
2378 GNUNET_free (pendingsession_tmp);
2380 GNUNET_assert (check == 0);
2385 endpoint = queue->content->mac;
2386 fm = endpoint->sending_messages_head;
2390 if (fm->session == queue->content)
2392 free_fragment_message (plugin, fm);
2397 // remove PendingMessage
2398 pm = queue->content->pending_message_head;
2401 GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
2402 queue->content->pending_message_tail, pm);
2403 GNUNET_free (pm->msg);
2405 pm = queue->content->pending_message_head;
2408 GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
2410 //Check that no ohter session on this endpoint for this session exits
2411 GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
2413 if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
2415 free_macendpoint (plugin, endpoint);
2416 //check if no endpoint with the same address exists
2417 GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
2421 if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2423 GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
2424 queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2426 GNUNET_free (queue);
2428 check_fragment_queue (plugin);
2432 * Function that can be used to force the plugin to disconnect
2433 * from the given peer and cancel all previous transmissions
2434 * (and their continuation).
2436 * @param cls closure
2437 * @param target peer from which to disconnect
2440 wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
2442 struct Plugin *plugin = cls;
2443 struct Sessionqueue *queue;
2444 struct Sessionqueue *queue_next;
2445 struct MacEndpoint *endpoint = plugin->mac_head;
2446 struct MacEndpoint *endpoint_next;
2448 // just look at all the session for the needed one
2449 while (endpoint != NULL)
2451 queue = endpoint->sessions_head;
2452 endpoint_next = endpoint->next;
2453 while (queue != NULL)
2455 // content is never NULL
2456 GNUNET_assert (queue->content != NULL);
2457 queue_next = queue->next;
2459 (target, &(queue->content->target),
2460 sizeof (struct GNUNET_PeerIdentity)) == 0)
2462 free_session (plugin, queue, GNUNET_YES);
2467 endpoint = endpoint_next;
2472 * Convert the transports address to a nice, human-readable
2475 * @param cls closure
2476 * @param type name of the transport that generated the address
2477 * @param addr one of the addresses of the host, NULL for the last address
2478 * the specific address format depends on the transport
2479 * @param addrlen length of the address
2480 * @param numeric should (IP) addresses be displayed in numeric form?
2481 * @param timeout after how long should we give up?
2482 * @param asc function to call on each string
2483 * @param asc_cls closure for asc
2486 wlan_plugin_address_pretty_printer (void *cls, const char *type,
2487 const void *addr, size_t addrlen,
2489 struct GNUNET_TIME_Relative timeout,
2490 GNUNET_TRANSPORT_AddressStringCallback asc,
2494 const unsigned char *input;
2496 //GNUNET_assert(cls !=NULL);
2497 if (addrlen != sizeof (struct MacAddress))
2499 /* invalid address (MAC addresses have 6 bytes) */
2502 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2503 "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
2506 asc (asc_cls, NULL);
2509 input = (const unsigned char *) addr;
2510 GNUNET_asprintf (&ret,
2511 "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
2512 type, PROTOCOL_PREFIX, input[0], input[1], input[2],
2513 input[3], input[4], input[5]);
2515 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2516 "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
2517 addrlen, numeric, type, ret);
2520 //only one mac address per plugin
2521 asc (asc_cls, NULL);
2527 * handels the data after all fragments are put together
2528 * @param cls macendpoint this messages belongs to
2529 * @param hdr pointer to the data
2532 wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
2534 struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
2535 struct Plugin *plugin = endpoint->plugin;
2536 struct WlanHeader *wlanheader;
2537 struct Session *session;
2539 const struct GNUNET_MessageHeader *temp_hdr;
2540 struct GNUNET_PeerIdentity tmpsource;
2543 GNUNET_assert (plugin != NULL);
2545 if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2549 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2550 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2554 if (ntohs (hdr->size) <
2555 sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
2557 //packet not big enought
2561 GNUNET_STATISTICS_update (plugin->env->stats,
2562 _("# wlan whole messages received"), 1,
2564 wlanheader = (struct WlanHeader *) hdr;
2566 session = search_session (plugin, endpoint, &wlanheader->source);
2568 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2569 crc = ntohl (wlanheader->crc);
2570 wlanheader->crc = 0;
2571 if (GNUNET_CRYPTO_crc32_n
2572 ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
2574 //wrong crc, dispose message
2575 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2576 "Wlan message header crc was wrong: %u != %u\n",
2577 GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
2578 ntohs (wlanheader->header.size)),
2580 hexdump ((void *) hdr, ntohs (hdr->size));
2584 //if not in session list
2585 if (session == NULL)
2588 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2589 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2590 ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
2591 sizeof (struct WlanHeader));
2593 //try if it is a hello message
2594 if (ntohs (wlanheader->header.size) >=
2595 ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
2597 if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2599 if (GNUNET_HELLO_get_id
2600 ((const struct GNUNET_HELLO_Message *) temp_hdr,
2601 &tmpsource) == GNUNET_OK)
2603 session = create_session (plugin, endpoint, &tmpsource);
2607 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2608 "WLAN client not in session list and hello message is not okay\n");
2615 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2616 "WLAN client not in session list and not a hello message\n");
2622 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2623 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2624 ntohs (wlanheader->header.size),
2625 ntohs (temp_hdr->size), sizeof (struct WlanHeader));
2630 //"receive" the message
2633 (&wlanheader->source, &session->target,
2634 sizeof (struct GNUNET_PeerIdentity)) != 0)
2638 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2639 "WLAN peer source id doesn't match packet peer source id: session %p\n",
2646 (&wlanheader->target, plugin->env->my_identity,
2647 sizeof (struct GNUNET_PeerIdentity)) != 0)
2651 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2652 "WLAN peer target id doesn't match our peer id: session %p\n",
2658 GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
2659 (const char *) temp_hdr,
2660 ntohs (hdr->size) - sizeof (struct WlanHeader),
2661 GNUNET_YES, GNUNET_NO);
2667 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2668 "wlan_data_message_handler got wrong message type: %u\n",
2675 * function to process the a message, give it to the higher layer
2676 * @param cls pointer to the plugin
2677 * @param client pointer to the session this message belongs to
2678 * @param hdr start of the message
2680 //TODO ATS informations
2682 process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2685 GNUNET_assert (client != NULL);
2686 GNUNET_assert (cls != NULL);
2687 struct Session *session = (struct Session *) client;
2688 struct Plugin *plugin = (struct Plugin *) cls;
2689 struct GNUNET_ATS_Information ats[2];
2691 ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
2692 ats[0].value = htonl (1);
2693 ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
2694 ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
2697 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2698 "Calling plugin->env->receive for session %p; %s; size: %u\n",
2699 session, wlan_plugin_address_to_string (NULL,
2705 plugin->env->receive (plugin->env->cls, &(session->target), hdr,
2706 (const struct GNUNET_ATS_Information *) &ats, 2,
2707 session, (const char *) &session->mac->addr,
2708 sizeof (session->mac->addr));
2712 * Function used for to process the data received from the wlan interface
2714 * @param cls the plugin handle
2715 * @param session_light pointer to the struct holding known informations
2716 * @param hdr hdr of the GNUNET_MessageHeader
2717 * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS for info
2720 wlan_data_helper (void *cls, struct Session_light *session_light,
2721 const struct GNUNET_MessageHeader *hdr,
2722 const struct Radiotap_rx *rxinfo)
2724 struct Plugin *plugin = cls;
2725 struct FragmentMessage *fm;
2726 struct FragmentMessage *fm2;
2727 struct GNUNET_PeerIdentity tmpsource;
2729 GNUNET_assert (plugin != NULL);
2732 if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2735 //TODO better DOS protection, error handling
2736 //TODO test first than create session
2737 GNUNET_assert (session_light != NULL);
2740 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2741 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_HELLO size: %u; %s\n",
2742 ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2743 session_light->addr.
2747 if (session_light->macendpoint == NULL)
2749 session_light->macendpoint =
2750 get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2754 if (GNUNET_HELLO_get_id
2755 ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
2757 session_light->session =
2758 search_session (plugin, session_light->macendpoint, &tmpsource);
2759 if (session_light->session == NULL)
2761 session_light->session =
2762 create_session (plugin, session_light->macendpoint, &tmpsource);
2764 GNUNET_STATISTICS_update (plugin->env->stats,
2765 _("# wlan hello messages received"), 1,
2767 plugin->env->receive (plugin->env->cls, &session_light->session->target,
2768 hdr, NULL, 0, session_light->session,
2769 (const char *) &session_light->session->mac->addr,
2770 sizeof (session_light->session->mac->addr));
2774 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2775 "WLAN client not in session list and hello message is not okay\n");
2782 else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT)
2785 GNUNET_assert (session_light != NULL);
2786 if (session_light->macendpoint == NULL)
2788 session_light->macendpoint =
2789 get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2793 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2794 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT with size: %u; mac endpoint %p: %s\n",
2795 ntohs (hdr->size), session_light->macendpoint,
2796 wlan_plugin_address_to_string (NULL,
2797 session_light->addr.mac,
2801 GNUNET_STATISTICS_update (plugin->env->stats,
2802 _("# wlan fragments received"), 1, GNUNET_NO);
2804 GNUNET_DEFRAGMENT_process_fragment (session_light->macendpoint->defrag,
2807 if (ret == GNUNET_NO)
2809 session_light->macendpoint->dups++;
2811 else if (ret == GNUNET_OK)
2813 session_light->macendpoint->fragc++;
2815 set_next_send (plugin);
2821 else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT_ACK)
2823 GNUNET_assert (session_light != NULL);
2824 if (session_light->macendpoint == NULL)
2826 session_light->macendpoint =
2827 get_macendpoint (plugin, &session_light->addr, GNUNET_NO);
2830 if (session_light->macendpoint == NULL)
2833 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2834 "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n",
2835 ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2836 session_light->addr.mac,
2843 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2844 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; mac endpoint: %p; %s\n",
2845 ntohs (hdr->size), session_light->macendpoint,
2846 wlan_plugin_address_to_string (NULL,
2847 session_light->addr.mac,
2850 fm = session_light->macendpoint->sending_messages_head;
2854 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"),
2856 int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
2858 if (ret == GNUNET_OK)
2860 #if DEBUG_wlan_retransmission > 1
2861 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2862 "Got last ack, finished fragment message %p\n", fm);
2864 session_light->macendpoint->acks++;
2865 fm->session->last_activity = GNUNET_TIME_absolute_get ();
2866 session_light->macendpoint->last_activity = fm->session->last_activity;
2867 free_fragment_message (plugin, fm);
2868 check_fragment_queue (plugin);
2871 if (ret == GNUNET_NO)
2873 #if DEBUG_wlan_retransmission > 1
2874 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2875 "Got ack for: %p\n", fm);
2877 session_light->macendpoint->acks++;
2880 if (ret == GNUNET_SYSERR)
2888 #if DEBUG_wlan_retransmission > 1
2889 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2890 "WLAN fragment not in fragment list\n");
2898 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2899 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2900 ntohs (hdr->type), ntohs (hdr->size));
2906 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2907 "Helper finished\n");
2914 * Function to print mac addresses nice *
2915 * @param pointer to 6 byte with the mac address
2916 * @return pointer to the chars which hold the print out
2919 macprinter (const u_int8_t * mac)
2921 static char macstr[20];
2923 GNUNET_snprintf (macstr, sizeof (macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2924 mac[2], mac[3], mac[4], mac[5]);
2930 * Function for the scheduler if a mac endpoint times out
2931 * @param cls pointer to the MacEndpoint
2932 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
2935 macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2937 struct MacEndpoint *endpoint = cls;
2939 GNUNET_assert (endpoint != NULL);
2940 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2941 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2945 if (GNUNET_TIME_absolute_get_remaining
2946 (GNUNET_TIME_absolute_add
2947 (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
2949 GNUNET_assert (endpoint->plugin != NULL);
2950 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
2951 _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
2952 free_macendpoint (endpoint->plugin, endpoint);
2956 endpoint->timeout_task =
2957 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
2963 * function to create an macendpoint
2964 * @param plugin pointer to the plugin struct
2965 * @param addr pointer to the macaddress
2966 * @return returns a macendpoint
2968 static struct MacEndpoint *
2969 create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr)
2971 struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint));
2973 GNUNET_assert (plugin != NULL);
2974 GNUNET_STATISTICS_update (plugin->env->stats,
2975 _("# wlan mac endpoints created"), 1, GNUNET_NO);
2976 newend->addr = *addr;
2977 newend->plugin = plugin;
2978 newend->addr = *addr;
2979 newend->fragment_messages_out_count = 0;
2981 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
2982 MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
2983 newend, &wlan_data_message_handler,
2985 newend->last_activity = GNUNET_TIME_absolute_get ();
2986 newend->timeout_task =
2987 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
2990 plugin->mac_count++;
2991 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2992 plugin->mac_count, GNUNET_NO);
2993 GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend);
2995 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2996 "New Mac Endpoint %p: %s\n", newend,
2997 wlan_plugin_address_to_string (NULL, newend->addr.mac, 6));
3003 * Function used for to process the data from the suid process
3005 * @param cls the plugin handle
3006 * @param client client that send the data (not used)
3007 * @param hdr header of the GNUNET_MessageHeader
3010 wlan_process_helper (void *cls, void *client,
3011 const struct GNUNET_MessageHeader *hdr)
3013 struct Plugin *plugin = cls;
3014 struct ieee80211_frame *wlanIeeeHeader = NULL;
3015 struct Session_light *session_light = NULL;
3016 struct Radiotap_rx *rxinfo;
3017 const struct GNUNET_MessageHeader *temp_hdr = NULL;
3022 GNUNET_assert (plugin != NULL);
3023 switch (ntohs (hdr->type))
3025 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
3027 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3028 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
3032 GNUNET_STATISTICS_update (plugin->env->stats,
3033 _("# wlan WLAN_HELPER_DATA received"), 1,
3035 //call wlan_process_helper with the message inside, later with wlan: analyze signal
3036 if (ntohs (hdr->size) <
3037 sizeof (struct ieee80211_frame) +
3038 2 * sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
3041 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3042 "Size of packet is too small; size: %u min size: %u\n",
3044 sizeof (struct ieee80211_frame) +
3045 sizeof (struct GNUNET_MessageHeader));
3048 /* FIXME: restart SUID process */
3052 rxinfo = (struct Radiotap_rx *) &hdr[1];
3053 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
3055 //process only if it is an broadcast or for this computer both with the gnunet bssid
3059 (&(wlanIeeeHeader->i_addr3), &mac_bssid_gnunet,
3060 sizeof (struct MacAddress)) == 0)
3062 //check for broadcast or mac
3064 (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
3065 sizeof (struct MacAddress)) == 0) ||
3067 (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
3068 sizeof (struct MacAddress)) == 0))
3070 //if packet is from us return
3072 (&(wlanIeeeHeader->i_addr2), &(plugin->mac_address),
3073 sizeof (struct MacAddress)) == 0))
3077 // process the inner data
3081 ntohs (hdr->size) - sizeof (struct ieee80211_frame) -
3082 sizeof (struct GNUNET_MessageHeader) - sizeof (struct Radiotap_rx);
3084 session_light = GNUNET_malloc (sizeof (struct Session_light));
3085 memcpy (&session_light->addr, &(wlanIeeeHeader->i_addr2),
3086 sizeof (struct MacAddress));
3087 //session_light->session = search_session(plugin,session_light->addr);
3088 GNUNET_STATISTICS_update (plugin->env->stats,
3089 _("# wlan messages for this client received"),
3093 while (pos < datasize)
3095 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1] + pos;
3096 if (ntohs (temp_hdr->size) <= datasize + pos)
3098 GNUNET_STATISTICS_update (plugin->env->stats,
3100 ("# wlan messages inside WLAN_HELPER_DATA received"),
3102 wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
3107 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3108 "Size of packet is too small; size: %u > size of packet: %u\n",
3109 ntohs (temp_hdr->size), datasize + pos);
3112 pos += ntohs (temp_hdr->size);
3117 GNUNET_free (session_light);
3122 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3123 "Func wlan_process_helper got wrong MAC: %s\n",
3124 macprinter (wlanIeeeHeader->i_addr1));
3131 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3132 "Func wlan_process_helper got wrong BSSID: %s\n",
3133 macprinter (wlanIeeeHeader->i_addr2));
3137 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
3138 //TODO more control messages
3139 if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
3142 /* FIXME: restart SUID process */
3145 memcpy (&plugin->mac_address, &hdr[1], sizeof (struct MacAddress));
3147 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3148 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
3149 wlan_plugin_address_to_string (cls, &plugin->mac_address,
3153 plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
3154 &plugin->mac_address,
3155 sizeof (struct MacAddress));
3159 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3160 "Func wlan_process_helper got unknown message with number %u, size %u\n",
3161 ntohs (hdr->type), ntohs (hdr->size));
3164 #if DEBUG_wlan_msg_dump > 1
3165 hexdump (hdr, GNUNET_MIN (ntohs (hdr->size), 256));
3173 * Exit point from the plugin.
3174 * @param cls pointer to the api struct
3179 libgnunet_plugin_transport_wlan_done (void *cls)
3181 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3182 struct Plugin *plugin = api->cls;
3183 struct MacEndpoint *endpoint = plugin->mac_head;
3184 struct MacEndpoint *endpoint_next;
3187 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3188 "libgnunet_plugin_transport_wlan_done started\n");
3191 wlan_transport_stop_wlan_helper (plugin);
3193 GNUNET_assert (cls != NULL);
3195 while (endpoint != NULL)
3197 endpoint_next = endpoint->next;
3198 free_macendpoint (plugin, endpoint);
3199 endpoint = endpoint_next;
3204 if (plugin->suid_tokenizer != NULL)
3205 GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
3207 if (plugin->data_tokenizer != NULL)
3208 GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
3210 GNUNET_free_non_null (plugin->interface);
3211 GNUNET_free (plugin);
3217 * Entry point for the plugin.
3219 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3220 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3223 libgnunet_plugin_transport_wlan_init (void *cls)
3225 //struct GNUNET_SERVICE_Context *service;
3226 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3227 struct GNUNET_TRANSPORT_PluginFunctions *api;
3228 struct Plugin *plugin;
3230 GNUNET_assert (cls != NULL);
3232 plugin = GNUNET_malloc (sizeof (struct Plugin));
3234 plugin->pendingsessions = 0;
3235 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
3236 plugin->pendingsessions, GNUNET_NO);
3237 plugin->mac_count = 0;
3238 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
3239 plugin->mac_count, GNUNET_NO);
3240 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3241 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3242 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3243 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
3244 GNUNET_BANDWIDTH_value_init (100 * 1024 *
3247 plugin->suid_tokenizer =
3248 GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
3250 plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
3252 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3253 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3255 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3257 api->send = &wlan_plugin_send;
3258 api->disconnect = &wlan_plugin_disconnect;
3259 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3260 api->check_address = &wlan_plugin_address_suggested;
3261 api->address_to_string = &wlan_plugin_address_to_string;
3265 if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
3267 if (GNUNET_SYSERR ==
3268 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
3269 "TESTMODE", &(plugin->testmode)))
3270 plugin->testmode = 0; //default value
3273 if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
3275 if (GNUNET_CONFIGURATION_get_value_string
3276 (env->cfg, "transport-wlan", "INTERFACE",
3277 &(plugin->interface)) != GNUNET_YES)
3279 libgnunet_plugin_transport_wlan_done (api);
3285 wlan_transport_start_wlan_helper (plugin);
3286 set_next_beacon_time (plugin);
3287 set_next_send (plugin);
3289 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3290 "wlan init finished\n");
3296 /* end of plugin_transport_wlan.c */