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
151 u_int8_t i_addr1[IEEE80211_ADDR_LEN];
152 u_int8_t i_addr2[IEEE80211_ADDR_LEN];
153 u_int8_t i_addr3[IEEE80211_ADDR_LEN];
155 #if DEBUG_wlan_ip_udp_packets_on_air
162 * Initial handshake message for a session.
164 struct WelcomeMessage
167 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
169 struct GNUNET_MessageHeader header;
172 * Identit*mac_y of the node connecting (TCP client)
174 struct GNUNET_PeerIdentity clientIdentity;
179 * Encapsulation of all of the state of the plugin.
186 struct GNUNET_TRANSPORT_PluginEnvironment *env;
189 * List of open connections. head
191 struct MacEndpoint * mac_head;
194 * List of open connections. tail
196 struct MacEndpoint * mac_tail;
199 * Number of connections
201 unsigned int mac_count;
204 * encapsulation of data from the local wlan helper program
206 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
209 * encapsulation of packets received from the wlan helper
211 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
213 * encapsulation of packets received
215 struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
218 * stdout pipe handle for the gnunet-wlan-helper process
220 struct GNUNET_DISK_PipeHandle *server_stdout;
223 * stdout file handle for the gnunet-wlan-helper process
225 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
228 * stdin pipe handle for the gnunet-wlan-helper process
230 struct GNUNET_DISK_PipeHandle *server_stdin;
233 * stdin file handle for the gnunet-wlan-helper process
235 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
238 * ID of the gnunet-wlan-server std read task
240 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
243 * ID of the gnunet-wlan-server std read task
245 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
248 * ID of the delay task for writing
250 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
253 * The process id of the wlan process
255 struct GNUNET_OS_Process *server_proc;
258 * The interface of the wlan card given to us by the user.
263 * The mac_address of the wlan card given to us by the helper.
265 struct MacAddress mac_address;
268 * Sessions currently pending for transmission
269 * to this peer, if any.
271 struct Sessionqueue * pending_Sessions_head;
274 * Sessions currently pending for transmission
275 * to this peer (tail), if any.
277 struct Sessionqueue * pending_Sessions_tail;
280 * number of pending sessions
282 unsigned int pendingsessions;
285 * Messages in the fragmentation queue, head
287 struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
290 * Messages in the in Queue, head
292 struct Receive_Message_Queue * receive_messages_head;
295 * Messages in the in Queue, tail
297 struct Receive_Message_Queue * receive_messages_teil;
300 * number of messages in the in queue
302 unsigned int pending_receive_messages;
305 * time of the next "hello-beacon"
307 struct GNUNET_TIME_Absolute beacon_time;
310 * queue to send acks for received fragments (head)
312 struct AckSendQueue * ack_send_queue_head;
315 * queue to send acks for received fragments (tail)
317 struct AckSendQueue * ack_send_queue_tail;
321 * Struct to store data if file write did not accept the whole packet
325 struct Plugin * plugin;
327 struct GNUNET_MessageHeader * msgstart;
332 * Queue of sessions, for the general session queue and the pending session queue
337 struct Sessionqueue * next;
338 struct Sessionqueue * prev;
339 struct Session * content;
343 * Queue for the fragments received
346 struct Receive_Fragment_Queue
348 struct Receive_Fragment_Queue * next;
349 struct Receive_Fragment_Queue * prev;
353 struct Radiotap_rx rxinfo;
357 struct MacEndpoint_id_fragment_triple
359 struct MacEndpoint * endpoint;
361 struct FragmentMessage * fm;
365 struct Plugin_Session_pair
367 struct Plugin * plugin;
368 struct Session * session;
372 * Queue for the fragments received
374 struct Receive_Message_Queue
376 struct Receive_Message_Queue * next;
378 struct Receive_Message_Queue * prev;
381 * current number for message incoming, to distinguish between the messages
383 uint32_t message_id_in;
386 * size of the message received,
387 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
388 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
393 * Sorted queue with the fragments received; head
396 struct Receive_Fragment_Queue * frag_head;
399 * Sorted queue with the fragments received; tail
402 struct Receive_Fragment_Queue * frag_tail;
405 * Session this fragment belongs to
408 //struct Session * session;
411 * Mac enddpoint this fragment belongs to
414 struct MacEndpoint * endpoint;
417 * Timeout value for the pending message.
419 struct GNUNET_TIME_Absolute timeout;
422 * Bitfield of received fragments
425 uint64_t received_fragments;
429 * Information kept for each message that is yet to
432 struct PendingMessage
437 struct PendingMessage * next;
441 struct PendingMessage * prev;
444 * The pending message
449 * Size of the message
454 * Continuation function to call once the message
455 * has been sent. Can be NULL if there is no
456 * continuation to call.
458 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
461 * Cls for transmit_cont
463 void * transmit_cont_cls;
466 * Timeout value for the pending message.
468 struct GNUNET_TIME_Absolute timeout;
473 * Queue for acks to send for fragments recived
479 * next ack in the ack send queue
481 struct AckSendQueue * next;
483 * previous ack in the ack send queue
485 struct AckSendQueue * prev;
487 * pointer to the session this ack belongs to
489 struct MacEndpoint * endpoint;
491 * ID of message, to distinguish between the messages, picked randomly.
496 * Bit field for received fragments
498 uint64_t fragments_field;
503 * Session infos gathered from a messages
509 * the session this message belongs to
511 struct Session * session;
515 struct MacAddress addr;
520 struct MacEndpoint * macendpoint;
524 * Session handle for connections.
532 struct SessionHeader header;
535 * Message currently pending for transmission
536 * to this peer, if any. head
538 struct PendingMessage * pending_message_head;
541 * Message currently pending for transmission
542 * to this peer, if any. tail
544 struct PendingMessage * pending_message_tail;
547 * To whom are we talking to (set to our identity
548 * if we are still waiting for the welcome message)
550 struct GNUNET_PeerIdentity target;
553 * Address of the other peer (either based on our 'connect'
554 * call or on our 'accept' call).
559 * Last activity on this connection. Used to select preferred
562 struct GNUNET_TIME_Absolute last_activity;
567 struct MacEndpoint * mac;
572 * Struct to represent one network card connection
577 * Pointer to the global plugin struct.
579 struct Plugin *plugin;
581 * Struct to hold the session reachable over this mac; head
583 struct Sessionqueue * sessions_head;
585 * Struct to hold the session reachable over this mac; tail
587 struct Sessionqueue * sessions_tail;
591 struct MacEndpoint *next;
595 struct MacEndpoint *prev;
600 struct MacAddress addr;
603 * count of messages in the fragment out queue for this session
606 int fragment_messages_out_count;
609 * count of messages in the fragment in queue for this session
612 int fragment_messages_in_count;
620 * backlog for incoming message ids
622 uint32_t message_id_backlog[MESSAGE_ID_BACKLOG_SIZE];
624 * position in the backlog
626 int message_id_backlog_pos;
630 * Struct for Messages in the fragment queue
633 struct FragmentMessage
636 * heap pointer of this message
638 struct GNUNET_CONTAINER_HeapNode * node;
641 * Session this message belongs to
644 struct Session *session;
647 * This is a doubly-linked list.
649 struct FragmentMessage *next;
652 * This is a doubly-linked list.
654 struct FragmentMessage *prev;
657 * The pending message
662 * 0 if not in ack queue
669 * Timeout value for the pending message.
671 struct GNUNET_TIME_Absolute timeout;
674 * Timeout value for the pending fragments.
675 * Stores the time when the next msg fragment ack has to be received
677 struct GNUNET_TIME_Absolute next_ack;
680 * bitfield with all acks received for this message
682 uint64_t ack_bitfield;
685 * Size of the message
690 * pos / next fragment number in the message, for fragmentation/segmentation,
691 * some acks can be missing but there is still time
693 uint32_t message_pos;
696 * current number for message outgoing, to distinguish between the messages
698 uint32_t message_id_out;
702 * Header for messages which need fragmentation
704 struct FragmentationAckHeader
707 struct GNUNET_MessageHeader header;
710 * ID of message, to distinguish between the messages, picked randomly.
712 uint32_t message_id GNUNET_PACKED;
715 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
717 uint64_t fragment_field GNUNET_PACKED;
722 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
724 free_session(struct Plugin * plugin, struct Sessionqueue * queue,
725 int do_free_macendpoint);
728 * Generates a nice hexdump of a memory area.
730 * \param mem pointer to memory to dump
731 * \param length how many bytes to dump
734 hexdump(void *mem, unsigned length)
737 char *src = (char*) mem;
740 "dumping %u bytes from %p\r\n"
741 " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\r\n",
746 for (i = 0; i < length; i += 16, src += 16)
750 t += sprintf(t, "%04x: ", i);
751 for (j = 0; j < 16; j++)
754 t += sprintf(t, "%02X", src[j] & 0xff);
756 t += sprintf(t, " ");
757 t += sprintf(t, j % 2 ? " " : "-");
760 t += sprintf(t, " ");
761 for (j = 0; j < 16; j++)
765 if (isprint((unsigned char)src[j]))
766 t += sprintf(t, "%c", src[j]);
768 t += sprintf(t, ".");
772 t += sprintf(t, " ");
776 t += sprintf(t, "\r\n");
782 * Sets a bit active in the bitArray. Increment bit-specific
783 * usage counter on disk only if below 4bit max (==15).
785 * @param bitArray memory area to set the bit in
786 * @param bitIdx which bit to set
789 setBit(char *bitArray, unsigned int bitIdx)
792 unsigned int targetBit;
794 arraySlot = bitIdx / 8;
795 targetBit = (1L << (bitIdx % 8));
796 bitArray[arraySlot] |= targetBit;
800 * Checks if a bit is active in the bitArray
802 * @param bitArray memory area to set the bit in
803 * @param bitIdx which bit to test
804 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
807 testBit(char *bitArray, unsigned int bitIdx)
810 unsigned int targetBit;
813 targetBit = (1L << (bitIdx % 8));
814 if (bitArray[slot] & targetBit)
820 * get the next message number, at the moment just a random one
821 * @return returns the next valid message-number for sending packets
824 get_next_message_id()
826 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
829 static struct MacEndpoint *
830 create_macendpoint(struct Plugin *plugin, const struct MacAddress *addr)
832 struct MacEndpoint * newend = GNUNET_malloc(sizeof (struct MacEndpoint));
833 newend->addr = *addr;
834 newend->plugin = plugin;
835 newend->addr = *addr;
836 newend->fragment_messages_out_count = 0;
837 newend->fragment_messages_in_count = 0;
838 newend->message_id_backlog_pos = 0;
841 GNUNET_CONTAINER_DLL_insert_tail(plugin->mac_head, plugin->mac_tail, newend);
847 * Function to find a MacEndpoint with a specific mac addr
848 * @param plugin pointer to the plugin struct
849 * @param addr pointer to the mac address
850 * @param create_new GNUNET_YES if a new end point should be created
853 static struct MacEndpoint *
854 get_macendpoint(struct Plugin *plugin, const struct MacAddress *addr,
857 struct MacEndpoint * queue = plugin->mac_head;
858 while (queue != NULL)
860 GNUNET_assert (queue->sessions_head != NULL);
861 if (memcmp(addr, &queue->addr, sizeof(struct MacAddress)) == 0)
862 return queue; /* session found */
866 if (create_new == GNUNET_YES)
868 return create_macendpoint(plugin, addr);
877 * search for a session with the addr and peer id
879 * @param plugin pointer to the plugin struct
880 * @param addr pointer to the mac address of the peer
881 * @param peer pointer to the peerid
882 * @return returns the session
884 static struct Session *
885 search_session(struct Plugin *plugin, const struct MacAddress *addr,
886 const struct GNUNET_PeerIdentity * peer)
888 struct MacEndpoint * endpoint = get_macendpoint(plugin, addr, GNUNET_NO);
889 if (endpoint == NULL)
893 struct Sessionqueue * queue = endpoint->sessions_head;
895 while (queue != NULL)
897 GNUNET_assert (queue->content != NULL);
898 if (memcmp(peer, &queue->content->target,
899 sizeof(struct GNUNET_PeerIdentity)) == 0)
900 return queue->content; /* session found */
907 * Function called for a quick conversion of the binary address to
908 * a numeric address. Note that the caller must not free the
909 * address and that the next call to this function is allowed
910 * to override the address again.
913 * @param addr binary address
914 * @param addrlen length of the address
915 * @return string representing the same address
918 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
921 const struct MacAddress *mac;
923 if (addrlen != sizeof(struct MacAddress))
929 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
930 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
931 mac->mac[4], mac->mac[5]);
936 * create a new session
938 * @param plugin pointer to the plugin struct
939 * @param addr pointer to the mac endpoint of the peer
940 * @return returns the session
943 static struct Session *
944 create_session(struct Plugin *plugin, struct MacEndpoint * endpoint,
945 const struct GNUNET_PeerIdentity * peer)
947 GNUNET_assert(endpoint != NULL);
948 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
950 GNUNET_CONTAINER_DLL_insert_tail(endpoint->sessions_head, endpoint->sessions_tail, queue);
952 queue->content = GNUNET_malloc (sizeof (struct Session));
953 queue->content->mac = endpoint;
954 memcpy(&(queue->content->target), peer, sizeof(struct GNUNET_PeerIdentity));
957 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
959 wlan_plugin_address_to_string(NULL, endpoint->addr.mac, 6));
962 return queue->content;
966 * Get session from address, create if no session exists
968 * @param plugin pointer to the plugin struct
969 * @param addr pointer to the mac address of the peer
970 * @param peer pointer to the peerid
971 * @return returns the session
973 static struct Session *
974 get_session(struct Plugin *plugin, const struct MacAddress *addr,
975 const struct GNUNET_PeerIdentity * peer)
977 struct Session * session = search_session(plugin, addr, peer);
978 struct MacEndpoint * mac;
981 mac = get_macendpoint(plugin, addr, GNUNET_YES);
982 return create_session(plugin, mac, peer);
986 * Queue the session to send data
987 * checks if there is a message pending
988 * checks if this session is not allready in the queue
989 * @param plugin pointer to the plugin
990 * @param session pointer to the session to add
993 queue_session(struct Plugin *plugin, struct Session * session)
995 struct Sessionqueue * queue = plugin->pending_Sessions_head;
997 if (session->pending_message_head != NULL)
999 while (queue != NULL)
1001 // content is never NULL
1002 GNUNET_assert (queue->content != NULL);
1003 // is session already in queue?
1004 if (session == queue->content)
1009 queue = queue->next;
1012 // Session is not in the queue
1014 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
1015 queue->content = session;
1017 //insert at the tail
1018 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
1019 plugin->pending_Sessions_tail, queue);
1020 plugin->pendingsessions++;
1026 * Function to schedule the write task, executed after a delay
1027 * @param cls pointer to the plugin struct
1028 * @param tc GNUNET_SCHEDULER_TaskContext pointer
1031 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1033 struct Plugin * plugin = cls;
1034 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1036 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1039 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
1040 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1042 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1043 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1044 &do_transmit, plugin);
1049 * Function to calculate the time of the next periodic "hello-beacon"
1050 * @param plugin pointer to the plugin struct
1054 set_next_beacon_time(struct Plugin * const plugin)
1056 //under 10 known peers: once a second
1057 if (plugin->mac_count < 10)
1059 plugin->beacon_time = GNUNET_TIME_absolute_add(
1060 GNUNET_TIME_absolute_get(),
1061 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
1062 HALLO_BEACON_SCALING_FACTOR));
1064 //under 30 known peers: every 10 seconds
1065 else if (plugin->mac_count < 30)
1067 plugin->beacon_time = GNUNET_TIME_absolute_add(
1068 GNUNET_TIME_absolute_get(),
1069 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
1070 10 * HALLO_BEACON_SCALING_FACTOR));
1072 //over 30 known peers: once a minute
1075 plugin->beacon_time = GNUNET_TIME_absolute_add(
1076 GNUNET_TIME_absolute_get(),
1077 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,
1078 HALLO_BEACON_SCALING_FACTOR));
1083 * Function to get the timeout value for acks for this session
1084 * @param fm pointer to the FragmentMessage to get the next timeout
1085 * @return time until the next ack should be received, in GNUNET_TIME_Relative
1087 static struct GNUNET_TIME_Relative
1088 get_ack_timeout(struct FragmentMessage * fm)
1090 return FRAGMENT_TIMEOUT;
1094 * Function to set the timer for the next timeout of the fragment queue
1095 * @param plugin the handle to the plugin struct
1099 set_next_send(struct Plugin * const plugin)
1101 struct FragmentMessage * fm;
1102 struct GNUNET_TIME_Relative next_send;
1103 struct GNUNET_TIME_Absolute next_send_tmp;
1106 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1108 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
1109 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1112 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1114 //check if some acks are in the queue
1115 if (plugin->ack_send_queue_head != NULL)
1117 next_send = GNUNET_TIME_UNIT_ZERO;
1120 //check if there are some fragments in the queue
1123 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
1126 next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
1128 next_send = GNUNET_TIME_relative_min(next_send,
1129 GNUNET_TIME_absolute_get_remaining(next_send_tmp));
1136 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
1137 next_send.rel_value);
1141 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
1143 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1145 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1146 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1147 &do_transmit, plugin);
1152 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1153 &delay_fragment_task, plugin);
1158 * Function to get the next queued Session, removes the session from the queue
1159 * @param plugin pointer to the plugin struct
1160 * @return pointer to the session found, returns NULL if there is now session in the queue
1162 static struct Session *
1163 get_next_queue_session(struct Plugin * plugin)
1165 struct Session * session;
1166 struct Sessionqueue * sessionqueue;
1167 struct Sessionqueue * sessionqueue_alt;
1168 struct PendingMessage * pm;
1169 sessionqueue = plugin->pending_Sessions_head;
1171 while (sessionqueue != NULL)
1173 session = sessionqueue->content;
1175 GNUNET_assert(session != NULL);
1176 pm = session->pending_message_head;
1181 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1182 "pending message is empty, should not happen. session %p\n",
1187 GNUNET_assert(pm != NULL);
1189 //check for message timeout
1190 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1192 //check if session has no message in the fragment queue
1193 if (session->mac->fragment_messages_out_count
1194 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1196 plugin->pendingsessions--;
1197 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1198 plugin->pending_Sessions_tail, sessionqueue);
1199 GNUNET_free(sessionqueue);
1205 sessionqueue = sessionqueue->next;
1210 GNUNET_CONTAINER_DLL_remove(session->pending_message_head, session->pending_message_tail, pm);
1212 //call the cont func that it did not work
1213 if (pm->transmit_cont != NULL)
1214 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1216 GNUNET_free(pm->msg);
1219 if (session->pending_message_head == NULL)
1221 sessionqueue_alt = sessionqueue;
1222 sessionqueue = sessionqueue->next;
1223 plugin->pendingsessions--;
1224 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1225 plugin->pending_Sessions_tail, sessionqueue_alt);
1227 GNUNET_free(sessionqueue_alt);
1236 * frees the space of a message in the fragment queue (send queue)
1237 * @param plugin the plugin struct
1238 * @param fm message to free
1241 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1243 struct Session * session = fm->session;
1247 (session->mac->fragment_messages_out_count)--;
1248 GNUNET_free_non_null(fm->msg);
1249 GNUNET_CONTAINER_heap_remove_node(fm->node);
1252 queue_session(plugin, session);
1254 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1255 "free pending fragment messages, pending messages remaining %u\n",
1256 GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
1262 * Function to check if there is some space in the fragment queue
1263 * inserts a message if space is available
1264 * @param plugin the plugin struct
1268 check_fragment_queue(struct Plugin * plugin)
1270 struct Session * session;
1271 struct FragmentMessage * fm;
1272 struct GNUNET_PeerIdentity pid;
1274 struct PendingMessage * pm;
1276 if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1277 < FRAGMENT_QUEUE_SIZE)
1279 session = get_next_queue_session(plugin);
1280 if (session != NULL)
1282 pm = session->pending_message_head;
1283 GNUNET_CONTAINER_DLL_remove(session->pending_message_head, session->pending_message_tail, pm);
1284 session->mac->fragment_messages_out_count++;
1285 GNUNET_assert(pm != NULL);
1287 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1288 fm->message_size = pm->message_size;
1290 fm->session = session;
1291 fm->timeout.abs_value = pm->timeout.abs_value;
1292 fm->message_pos = 0;
1293 fm->next_ack = GNUNET_TIME_absolute_get();
1294 fm->message_id_out = get_next_message_id();
1295 fm->ack_bitfield = 0;
1296 fm->node = GNUNET_CONTAINER_heap_insert(
1297 plugin->pending_Fragment_Messages, fm,
1298 GNUNET_TIME_absolute_get().abs_value);
1300 GNUNET_assert(session !=NULL);
1302 if (pm->transmit_cont != NULL)
1304 pid = session->target;
1305 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1307 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1308 "called pm->transmit_cont for %p\n", session);
1314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1315 "no pm->transmit_cont for %p\n", session);
1320 if (session->pending_message_head != NULL)
1323 queue_session(plugin, session);
1329 //check if timeout changed
1330 set_next_send(plugin);
1334 * Funktion to check if all fragments where send and the acks received
1335 * frees the space if finished
1336 * @param plugin the plugin struct
1337 * @param fm the message to check
1340 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1342 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1343 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1344 - sizeof(struct FragmentationHeader)));
1345 uint64_t tmpfield = UINT64_MAX;
1346 tmpfield = tmpfield >> maxack;
1350 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1351 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1352 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1355 if (fm->ack_bitfield == tmpfield)
1358 #if DEBUG_wlan_retransmission
1359 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1360 "Finished sending and got all acks; message_id %u\n",
1361 fm->message_id_out);
1364 free_fragment_message(plugin, fm);
1366 check_fragment_queue(plugin);
1372 * Function to set the next fragment number
1373 * @param fm use this FragmentMessage
1377 set_next_message_fragment_pos(struct Plugin * plugin,
1378 struct FragmentMessage * fm)
1383 //check if retransmit is needed
1384 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1387 // be positive and try again later :-D
1388 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1389 // find first missing fragment
1391 fm->message_pos = 0;
1393 GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1396 #if DEBUG_wlan_retransmission
1397 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1398 "Retransmit; message_id %u; fragment number %i, size: %u\n",
1399 fm->message_id_out, fm->message_pos, fm->message_size);
1403 //test if ack 0 (or X) was already received
1404 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1412 * function to fill the radiotap header
1413 * @param plugin pointer to the plugin struct
1414 * @param endpoint pointer to the endpoint
1415 * @param header pointer to the radiotap header
1416 * @return GNUNET_YES at success
1419 getRadiotapHeader(struct Plugin * plugin, struct MacEndpoint * endpoint,
1420 struct Radiotap_Send * header)
1423 if (endpoint != NULL)
1425 header->rate = endpoint->rate;
1426 header->tx_power = endpoint->tx_power;
1427 header->antenna = endpoint->antenna;
1432 header->tx_power = 0;
1433 header->antenna = 0;
1440 * function to generate the wlan hardware header for one packet
1441 * @param Header address to write the header to
1442 * @param to_mac_addr address of the recipient
1443 * @param plugin pointer to the plugin struct
1444 * @return GNUNET_YES if there was no error
1447 getWlanHeader(struct ieee80211_frame * Header,
1448 const struct MacAddress * to_mac_addr, struct Plugin * plugin,
1452 const int rate = 11000000;
1454 Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
1455 Header->i_fc[1] = 0x00;
1456 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1457 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1458 memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
1460 tmp16 = (uint16_t*) Header->i_dur;
1461 *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
1463 #if DEBUG_wlan_ip_udp_packets_on_air
1467 Header->ip.ip_dst.s_addr = *((uint32_t*) &to_mac_addr->mac[2]);
1468 Header->ip.ip_src.s_addr = *((uint32_t*) &plugin->mac_address.mac[2]);
1469 Header->ip.ip_v = 4;
1470 Header->ip.ip_hl = 5;
1471 Header->ip.ip_p = 17;
1472 Header->ip.ip_ttl = 1;
1473 Header->ip.ip_len = htons(size + 8);
1474 Header->ip.ip_sum = 0;
1475 x =(uint16_t *) &Header->ip;
1476 count = sizeof(struct iph);
1479 /* This is the inner loop */
1480 crc += (unsigned short) * x++;
1483 /* Add left-over byte, if any */
1485 crc += * (unsigned char *) x;
1486 crc = (crc & 0xffff) + (crc >> 16);
1487 Header->ip.ip_sum = htons(~ (unsigned short) crc);
1490 Header->udp.len = htons(size - sizeof(struct ieee80211_frame));
1500 * @param msgbuf pointer tor the data
1501 * @param msgbuf_size size of the data
1503 * @return 32bit crc value
1507 getcrc32(const char *msgbuf, size_t msgbuf_size)
1510 return GNUNET_CRYPTO_crc32_n(msgbuf, msgbuf_size);;
1516 * @param msgbuf pointer tor the data
1517 * @param msgbuf_size size of the data
1519 * @return 16bit crc value
1523 getcrc16(const char *msgbuf, size_t msgbuf_size)
1525 //TODO calc some crc
1531 send_hello_beacon(struct Plugin * plugin)
1535 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1540 uint16_t hallo_size;
1541 struct GNUNET_MessageHeader * msgheader;
1542 struct ieee80211_frame * ieeewlanheader;
1543 struct Radiotap_Send * radioHeader;
1544 struct GNUNET_MessageHeader * msgheader2;
1546 hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1547 GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1548 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1549 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1552 msgheader = GNUNET_malloc(size);
1553 msgheader->size = htons(size);
1554 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1556 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1557 getRadiotapHeader(plugin, NULL, radioHeader);
1558 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1559 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin, size);
1561 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1562 msgheader2->size = htons(
1563 GNUNET_HELLO_size(*(plugin->env->our_hello))
1564 + sizeof(struct GNUNET_MessageHeader));
1566 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1567 memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1569 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1571 if (bytes == GNUNET_SYSERR)
1573 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1574 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1575 errno, strerror(errno));
1578 GNUNET_assert(bytes != GNUNET_SYSERR);
1579 GNUNET_assert(bytes == size);
1580 GNUNET_free(msgheader);
1582 set_next_beacon_time(plugin);
1583 set_next_send(plugin);
1588 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1593 struct GNUNET_MessageHeader * msgheader;
1594 struct ieee80211_frame * ieeewlanheader;
1595 struct Radiotap_Send * radioHeader;
1596 struct FragmentationAckHeader * msgheader2;
1598 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1600 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1601 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1604 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1605 "Sending ack for message_id %u with fragment field %u, size %u\n",
1606 ack->message_id, ack->fragments_field,
1607 size - sizeof(struct Radiotap_Send));
1610 msgheader = GNUNET_malloc(size);
1611 msgheader->size = htons(size);
1612 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1614 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1615 getRadiotapHeader(plugin, ack->endpoint, radioHeader);
1616 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1617 getWlanHeader(ieeewlanheader, &ack->endpoint->addr, plugin, size);
1619 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1620 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1621 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1622 msgheader2->message_id = htonl(ack->message_id);
1623 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1625 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1626 if (bytes == GNUNET_SYSERR)
1628 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1629 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1630 errno, strerror(errno));
1633 GNUNET_assert(bytes != GNUNET_SYSERR);
1634 GNUNET_assert(bytes == size);
1635 GNUNET_free(msgheader);
1636 set_next_send(plugin);
1641 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1643 struct Finish_send * finish = cls;
1644 struct Plugin * plugin;
1647 plugin = finish->plugin;
1648 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1650 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1652 GNUNET_free (finish->msgstart);
1653 GNUNET_free (finish);
1656 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1657 finish->msgheader, finish->size);
1658 GNUNET_assert (bytes != GNUNET_SYSERR);
1660 if (bytes != finish->size)
1662 finish->msgheader = finish->msgheader + bytes;
1663 finish->size = finish->size - bytes;
1664 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1665 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1666 &finish_sending, finish);
1670 GNUNET_free(finish->msgstart);
1671 GNUNET_free(finish);
1672 set_next_send(plugin);
1677 * Function called when wlan helper is ready to get some data
1679 * @param cls closure
1680 * @param tc GNUNET_SCHEDULER_TaskContext
1683 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1685 struct Plugin * plugin = cls;
1687 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1688 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1691 struct Session * session;
1692 struct FragmentMessage * fm;
1693 struct ieee80211_frame * ieeewlanheader;
1694 struct Radiotap_Send * radioHeader;
1695 struct GNUNET_MessageHeader * msgheader;
1696 struct FragmentationHeader fragheader;
1697 struct FragmentationHeader * fragheaderptr;
1698 struct Finish_send * finish;
1699 struct AckSendQueue * ack;
1702 const char * copystart;
1706 if (plugin->ack_send_queue_head != NULL)
1708 ack = plugin->ack_send_queue_head;
1709 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1710 plugin->ack_send_queue_tail, ack);
1711 send_ack(plugin, ack);
1716 //test if a "hello-beacon" has to be send
1717 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1719 send_hello_beacon(plugin);
1723 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1727 session = fm->session;
1728 GNUNET_assert(session != NULL);
1730 // test if message timed out
1731 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1734 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1737 free_fragment_message(plugin, fm);
1738 check_fragment_queue(plugin);
1744 //if (fm->message_size > WLAN_MTU)
1746 size = sizeof(struct FragmentationHeader);
1748 set_next_message_fragment_pos(plugin, fm);
1750 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1753 fragheader.fragment_off_or_num = htons(fm->message_pos);
1754 fragheader.message_id = htonl(fm->message_id_out);
1755 copystart = fm->msg + copyoffset;
1756 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1757 WLAN_MTU - sizeof(struct FragmentationHeader));
1761 GNUNET_ERROR_TYPE_DEBUG,
1762 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1763 fm->message_id_out, fm->message_pos,
1764 copysize + sizeof(struct FragmentationHeader), copyoffset,
1765 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1768 if (copyoffset >= fm->message_size)
1771 GNUNET_ERROR_TYPE_ERROR,
1772 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1773 copyoffset, fm->message_size,
1774 WLAN_MTU - sizeof(struct FragmentationHeader), copysize,
1777 GNUNET_assert(copyoffset < fm->message_size);
1779 fragheader.header.size = htons(
1780 copysize + sizeof(struct FragmentationHeader));
1781 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1784 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1785 + sizeof(struct GNUNET_MessageHeader);
1786 msgheader = GNUNET_malloc(size);
1787 msgheader->size = htons(size);
1788 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1790 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1791 getRadiotapHeader(plugin, session->mac, radioHeader);
1793 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1794 getWlanHeader(ieeewlanheader, &(fm->session->mac->addr), plugin, size);
1796 //could be faster if content is just send and not copyed before
1797 //fragmentheader is needed
1798 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1799 memcpy(&ieeewlanheader[1], &fragheader,
1800 sizeof(struct FragmentationHeader));
1801 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1802 memcpy(&fragheaderptr[1], copystart, copysize);
1804 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1806 if (bytes == GNUNET_SYSERR)
1809 GNUNET_ERROR_TYPE_ERROR,
1810 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1811 errno, strerror(errno));
1814 GNUNET_assert(bytes != GNUNET_SYSERR);
1816 //check if this was the last fragment of this message, if true then queue at the end of the list
1817 if (copysize + copyoffset >= fm->message_size)
1819 GNUNET_assert(copysize + copyoffset == fm->message_size);
1821 GNUNET_CONTAINER_heap_update_cost(
1822 plugin->pending_Fragment_Messages, fm->node,
1823 MIN(fm->timeout.abs_value, fm->next_ack.abs_value));
1824 // if fragments have opimized timeouts
1825 //sort_fragment_into_queue(plugin,fm);
1828 #if DEBUG_wlan_retransmission
1830 GNUNET_ERROR_TYPE_DEBUG,
1831 "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1832 fm->message_id_out, fm->message_id_out, fm->message_pos,
1834 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1839 GNUNET_CONTAINER_heap_update_cost(
1840 plugin->pending_Fragment_Messages, fm->node,
1841 GNUNET_TIME_absolute_get().abs_value);
1846 finish = GNUNET_malloc(sizeof( struct Finish_send));
1847 finish->plugin = plugin;
1848 finish->msgheader = (char *) msgheader + bytes;
1849 finish->size = size - bytes;
1850 finish->msgstart = msgheader;
1852 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1854 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1855 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1856 &finish_sending, finish);
1861 GNUNET_free(msgheader);
1862 set_next_send(plugin);
1869 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1870 "do_transmit did nothing, should not happen!\n");
1874 * Another peer has suggested an address for this
1875 * peer and transport plugin. Check that this could be a valid
1876 * address. If so, consider adding it to the list
1879 * @param cls closure
1880 * @param addr pointer to the address
1881 * @param addrlen length of addr
1882 * @return GNUNET_OK if this is a plausible address for this peer
1886 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1888 //struct Plugin *plugin = cls;
1890 /* check if the address is plausible; if so,
1891 add it to our list! */
1893 GNUNET_assert(cls !=NULL);
1894 //FIXME mitm is not checked
1895 //Mac Address has 6 bytes
1898 /* TODO check for bad addresses like multicast, broadcast, etc */
1902 return GNUNET_SYSERR;
1906 * Function that can be used by the transport service to transmit
1907 * a message using the plugin.
1909 * @param cls closure
1910 * @param target who should receive this message
1911 * @param priority how important is the message
1912 * @param msgbuf the message to transmit
1913 * @param msgbuf_size number of bytes in 'msgbuf'
1914 * @param timeout when should we time out
1915 * @param session which session must be used (or NULL for "any")
1916 * @param addr the address to use (can be NULL if the plugin
1917 * is "on its own" (i.e. re-use existing TCP connection))
1918 * @param addrlen length of the address in bytes
1919 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1920 * otherwise the plugin may use other addresses or
1921 * existing connections (if available)
1922 * @param cont continuation to call once the message has
1923 * been transmitted (or if the transport is ready
1924 * for the next transmission call; or if the
1925 * peer disconnected...)
1926 * @param cont_cls closure for cont
1927 * @return number of bytes used (on the physical network, with overheads);
1928 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1929 * and does NOT mean that the message was not transmitted (DV)
1932 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1933 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1934 struct GNUNET_TIME_Relative timeout, struct Session *session,
1935 const void *addr, size_t addrlen, int force_address,
1936 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1938 struct Plugin * plugin = cls;
1939 struct PendingMessage * newmsg;
1940 struct WlanHeader * wlanheader;
1942 //check if msglen > 0
1943 GNUNET_assert(msgbuf_size > 0);
1945 //get session if needed
1946 if (session == NULL)
1948 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1950 session = get_session(plugin, addr, target);
1954 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1955 _("Wlan Address len %d is wrong\n"), addrlen);
1962 //queue message in session
1963 //test if there is no other message in the "queue"
1964 //FIXME: to many send requests
1965 if (session->pending_message_head != NULL)
1967 newmsg = session->pending_message_head;
1969 GNUNET_ERROR_TYPE_ERROR,
1970 "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",
1971 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1972 session->mac->fragment_messages_out_count);
1975 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1976 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1977 wlanheader = (struct WlanHeader *) newmsg->msg;
1978 //copy msg to buffer, not fragmented / segmented yet, but with message header
1979 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1980 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1981 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1982 memcpy(&(wlanheader->source), plugin->env->my_identity , sizeof(struct GNUNET_PeerIdentity));
1983 wlanheader->crc = 0;
1984 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1985 wlanheader->crc = htonl(
1986 getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)));
1987 //GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Wlan message Header crc: %u, %u\n",getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)), wlanheader->crc);
1988 //hexdump(newmsg->msg, msgbuf_size + sizeof(struct WlanHeader));
1990 newmsg->transmit_cont = cont;
1991 newmsg->transmit_cont_cls = cont_cls;
1992 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1994 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1996 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1998 GNUNET_CONTAINER_DLL_insert_tail(session->pending_message_head, session->pending_message_tail, newmsg);
2001 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2002 "New message for %p with size (incl wlan header) %u added\n", session,
2003 newmsg->message_size);
2007 queue_session(plugin, session);
2009 check_fragment_queue(plugin);
2010 //FIXME not the correct size
2016 * Iterate over the fragment messages of the given session.
2018 * @param cls argument to give to iterator
2019 * @param node node to iterate over
2020 * @param element value stored at the node
2021 * @param cost cost associated with the node
2022 * @return GNUNET_YES if we should continue to iterate,
2026 free_fragment_message_from_session(void *cls,
2027 struct GNUNET_CONTAINER_HeapNode *node, void *element,
2028 GNUNET_CONTAINER_HeapCostType cost)
2030 struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
2031 struct FragmentMessage * fm = (struct FragmentMessage*) element;
2033 if (fm->session == pair->session)
2036 free_fragment_message(pair->plugin, fm);
2043 * Search for fragment message with given id and session
2045 * @param cls argument to give to iterator
2046 * @param node node to iterate over
2047 * @param element value stored at the node
2048 * @param cost cost associated with the node
2049 * @return GNUNET_YES if we should continue to iterate,
2053 search_fragment_message_from_endpoint_and_id(void *cls,
2054 struct GNUNET_CONTAINER_HeapNode *node, void *element,
2055 GNUNET_CONTAINER_HeapCostType cost)
2057 struct MacEndpoint_id_fragment_triple * triple =
2058 (struct MacEndpoint_id_fragment_triple *) cls;
2059 struct FragmentMessage * fm = (struct FragmentMessage*) element;
2061 if ((fm->session->mac == triple->endpoint) && (fm->message_id_out
2062 == triple->message_id))
2072 * function to get the message in the fragement queue (out) of a session with a specific id
2073 * @param session pointer to the session
2074 * @param message_id id of the message
2075 * @return pointer to the struct FragmentMessage
2077 static struct FragmentMessage *
2078 get_fragment_message_from_endpoint_and_id(struct Plugin * plugin,
2079 struct MacEndpoint * endpoint, uint32_t message_id)
2081 struct MacEndpoint_id_fragment_triple triple;
2082 triple.endpoint = endpoint;
2083 triple.message_id = message_id;
2085 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
2086 &search_fragment_message_from_endpoint_and_id, &triple);
2091 * function to get the receive message of a session
2092 * @param plugin pointer to the plugin struct
2093 * @param endpoint MacEndpoint this fragment belongs to
2094 * @param message_id id of the message
2096 static struct Receive_Message_Queue *
2097 get_receive_message(struct Plugin * plugin, struct MacEndpoint * endpoint,
2098 uint32_t message_id)
2100 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2101 while (rec_message != NULL)
2103 if (rec_message->endpoint == endpoint && message_id
2104 == rec_message->message_id_in)
2108 rec_message = rec_message->next;
2114 * Function to dispose the fragments received for a message and the message
2115 * @param plugin pointer to the plugin struct
2116 * @param rec_message pointer to the struct holding the message which should be freed
2119 free_receive_message(struct Plugin* plugin,
2120 struct Receive_Message_Queue * rx_message)
2122 GNUNET_assert(rx_message !=NULL);
2123 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
2124 struct Receive_Fragment_Queue * rec_queue2;
2126 while (rec_queue != NULL)
2128 rec_queue2 = rec_queue;
2129 rec_queue = rec_queue->next;
2130 GNUNET_free(rec_queue2);
2133 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
2135 GNUNET_assert(plugin->pending_receive_messages > 0);
2136 GNUNET_assert(rx_message->endpoint != NULL);
2137 GNUNET_assert(rx_message->endpoint !=NULL);
2138 GNUNET_assert(rx_message->endpoint->fragment_messages_in_count > 0);
2140 plugin->pending_receive_messages--;
2141 rx_message->endpoint->fragment_messages_in_count--;
2142 GNUNET_free(rx_message);
2146 * function to check for timeouts
2147 * @param plugin pointer to the plugin struct
2150 check_receive_message_timeouts(struct Plugin * plugin)
2152 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2153 while (rec_message != NULL)
2155 if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
2158 free_receive_message(plugin, rec_message);
2160 rec_message = rec_message->next;
2166 * function to free a mac endpoint
2167 * @param plugin pointer to the plugin struct
2168 * @param endpoin pointer to the MacEndpoint to free
2171 free_macendpoint(struct Plugin * plugin, struct MacEndpoint * endpoin)
2173 struct Sessionqueue * sessions;
2174 struct Sessionqueue * sessions_next;
2175 GNUNET_assert(endpoin != NULL);
2176 sessions = endpoin->sessions_head;
2177 while (sessions != NULL)
2179 sessions_next = sessions->next;
2180 free_session(plugin, sessions, GNUNET_NO);
2181 sessions = sessions_next;
2184 GNUNET_CONTAINER_DLL_remove(plugin->mac_head,plugin->mac_tail,endpoin);
2185 GNUNET_free(endpoin);
2190 * function to free a session
2191 * @param plugin pointer to the plugin
2192 * @param queue pointer to the sessionqueue element to free
2193 * @param free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
2196 free_session(struct Plugin * plugin, struct Sessionqueue * queue,
2197 int do_free_macendpoint)
2199 struct Sessionqueue * pendingsession;
2200 struct Sessionqueue * pendingsession_tmp;
2201 struct PendingMessage * pm;
2202 //struct Receive_Message_Queue * receive_queue;
2203 struct Plugin_Session_pair pair;
2204 struct MacEndpoint * endpoint;
2207 GNUNET_assert(queue != NULL);
2208 GNUNET_assert(queue->content != NULL);
2211 //is this session pending for send
2212 pendingsession = plugin->pending_Sessions_head;
2213 while (pendingsession != NULL)
2215 pendingsession_tmp = pendingsession->next;
2216 if (pendingsession->content == queue->content)
2218 plugin->pendingsessions--;
2219 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2220 plugin->pending_Sessions_tail,
2222 GNUNET_free(pendingsession);
2224 GNUNET_assert (check == 0);
2227 pendingsession = pendingsession_tmp;
2230 //is something of this session in the fragment queue?
2231 pair.plugin = plugin;
2232 pair.session = queue->content;
2233 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
2234 &free_fragment_message_from_session, &pair);
2236 //dispose all received fragments
2237 /*receive_queue = get_receive_message_from_session(plugin, queue->content);
2238 while (receive_queue != NULL)
2240 free_receive_message(plugin, receive_queue);
2241 receive_queue = get_receive_message_from_session(plugin, queue->content);
2244 // remove PendingMessage
2245 pm = queue->content->pending_message_head;
2248 GNUNET_CONTAINER_DLL_remove(queue->content->pending_message_head,queue->content->pending_message_tail,pm);
2249 GNUNET_free_non_null(pm->msg);
2251 pm = queue->content->pending_message_head;
2254 endpoint = queue->content->mac;
2255 GNUNET_CONTAINER_DLL_remove(endpoint->sessions_head ,
2256 endpoint->sessions_tail,
2259 if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
2261 free_macendpoint(plugin, endpoint);
2263 GNUNET_free(queue->content);
2265 check_fragment_queue(plugin);
2269 * Function that can be used to force the plugin to disconnect
2270 * from the given peer and cancel all previous transmissions
2271 * (and their continuation).
2273 * @param cls closure
2274 * @param target peer from which to disconnect
2277 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
2279 struct Plugin *plugin = cls;
2280 struct Sessionqueue * queue;
2281 struct Sessionqueue * queue_next;
2282 struct MacEndpoint * endpoint = plugin->mac_head;
2283 struct MacEndpoint * endpoint_next;
2284 // just look at all the session for the needed one
2285 while (endpoint != NULL)
2287 queue = endpoint->sessions_head;
2288 endpoint_next = endpoint->next;
2289 while (queue != NULL)
2291 // content is never NULL
2292 GNUNET_assert (queue->content != NULL);
2293 queue_next = queue->next;
2294 if (memcmp(target, &(queue->content->target),
2295 sizeof(struct GNUNET_PeerIdentity)) == 0)
2297 free_session(plugin, queue, GNUNET_YES);
2302 endpoint = endpoint_next;
2307 * Convert the transports address to a nice, human-readable
2310 * @param cls closure
2311 * @param type name of the transport that generated the address
2312 * @param addr one of the addresses of the host, NULL for the last address
2313 * the specific address format depends on the transport
2314 * @param addrlen length of the address
2315 * @param numeric should (IP) addresses be displayed in numeric form?
2316 * @param timeout after how long should we give up?
2317 * @param asc function to call on each string
2318 * @param asc_cls closure for asc
2321 wlan_plugin_address_pretty_printer(void *cls, const char *type,
2322 const void *addr, size_t addrlen, int numeric,
2323 struct GNUNET_TIME_Relative timeout,
2324 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
2327 const unsigned char * input;
2329 //GNUNET_assert(cls !=NULL);
2332 /* invalid address (MAC addresses have 6 bytes) */GNUNET_break (0);
2336 input = (const unsigned char*) addr;
2337 GNUNET_snprintf(ret, sizeof(ret),
2338 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2339 input[0], input[1], input[2], input[3], input[4], input[5]);
2344 * Function to test if fragment number already exists in the fragments received
2346 * @param rec_message message this fragment belongs to
2347 * @param fh Fragmentheader of the fragment
2348 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2351 is_double_msg(struct Receive_Message_Queue * rx_msg,
2352 struct FragmentationHeader * fh)
2355 return testBit((char *) &rx_msg->received_fragments,
2356 ntohs(fh->fragment_off_or_num));
2361 * Function to insert a fragment in a queue of a message
2362 * @param session session the fragment belongs to
2363 * @param rec_queue fragment to add
2366 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2367 struct Receive_Fragment_Queue * rx_frag)
2369 GNUNET_assert(rx_message != NULL);
2370 GNUNET_assert(rx_frag != NULL);
2372 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2373 struct WlanHeader * wlanheader;
2375 //this is the first fragment of the message (fragment id 0)
2376 if (rx_frag->num == 0)
2378 wlanheader = (struct WlanHeader *) rx_frag->msg;
2379 rx_message->rec_size = ntohs(wlanheader->header.size);
2383 while (rx_frag2 != NULL)
2385 if (rx_frag2->num > rx_frag->num)
2387 //next element number is grater than the current num
2388 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2389 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2392 rx_frag2 = rx_frag2->next;
2395 //no element has a grater number
2396 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2398 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2402 * handels the data after all fragments are put together
2404 * @param session_light
2405 * @param hdr pointer to the data
2408 wlan_data_message_handler(void *cls, void *client,
2409 const struct GNUNET_MessageHeader *hdr)
2411 struct Plugin * plugin = (struct Plugin*) cls;
2412 struct Session_light * session_light = (struct Session_light *) client;
2413 struct WlanHeader * wlanheader;
2414 struct Session * session;
2415 //const char * tempmsg;
2416 const struct GNUNET_MessageHeader * temp_hdr;
2417 struct GNUNET_PeerIdentity tmpsource;
2420 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2425 GNUNET_ERROR_TYPE_DEBUG,
2426 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2430 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2431 + sizeof(struct GNUNET_MessageHeader))
2433 //packet not big enought
2437 GNUNET_assert(session_light != NULL);
2438 wlanheader = (struct WlanHeader *) hdr;
2440 if (session_light->session == NULL)
2442 session_light->session = search_session(plugin, &session_light->addr,
2443 &wlanheader->source);
2445 session = session_light->session;
2447 //tempmsg = (char*) &wlanheader[1];
2448 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2449 crc = ntohl(wlanheader->crc);
2450 wlanheader->crc = 0;
2451 if (getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)) != crc)
2453 //wrong crc, dispose message
2454 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2455 "Wlan message Header crc was wrong: %u != %u\n",
2456 getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)),
2458 hexdump((void *) hdr, ntohs(hdr->size));
2462 //if not in session list
2463 if (session == NULL)
2467 GNUNET_ERROR_TYPE_DEBUG,
2468 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2469 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2470 sizeof(struct WlanHeader));
2472 //try if it is a hello message
2473 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2474 + sizeof(struct WlanHeader))
2476 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2478 if (GNUNET_HELLO_get_id(
2479 (const struct GNUNET_HELLO_Message *) temp_hdr,
2480 &tmpsource) == GNUNET_OK)
2482 session_light->macendpoint = get_macendpoint(plugin,
2483 &session_light->addr, GNUNET_YES);
2484 session = create_session(plugin,
2485 session_light->macendpoint, &tmpsource);
2486 session_light->session = session;
2491 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2492 "WLAN client not in session list and hello message is not okay\n");
2499 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2500 "WLAN client not in session list and not a hello message\n");
2507 GNUNET_ERROR_TYPE_WARNING,
2508 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2509 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2510 sizeof(struct WlanHeader));
2515 //"receive" the message
2517 if (memcmp(&wlanheader->source, &session->target,
2518 sizeof(struct GNUNET_PeerIdentity)) != 0)
2522 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2523 "WLAN peer source id doesn't match packet peer source id: session %p\n",
2529 if (memcmp(&wlanheader->target, plugin->env->my_identity,
2530 sizeof(struct GNUNET_PeerIdentity)) != 0)
2534 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2535 "WLAN peer target id doesn't match our peer id: session %p\n",
2541 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2542 (const char *) temp_hdr,
2543 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2549 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2550 "wlan_data_message_handler got wrong message type\n");
2556 * Function to check if all fragments of a message have been received
2557 * @param plugin the plugin handle
2558 * @param session_light information of the message sender
2559 * @param rec_message pointer to the message that should be checked
2563 check_rx_finished_msg(struct Plugin* plugin,
2564 struct Session_light * session_light,
2565 struct Receive_Message_Queue * rx_message)
2567 GNUNET_assert(rx_message !=NULL);
2569 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2570 int packetsize = rx_message->rec_size;
2574 uint64_t bitfield = 0;
2577 //check if first fragment is present
2578 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2582 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2584 else if (packetsize < sizeof(struct WlanHeader)
2585 + sizeof(struct GNUNET_MessageHeader))
2588 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2590 free_receive_message(plugin, rx_message);
2594 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2596 bitfield = ~bitfield;
2597 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2598 if (rx_message->received_fragments == bitfield)
2601 while (rx_frag != NULL)
2603 sum += rx_frag->size;
2604 rx_frag = rx_frag->next;
2606 //sum should always be smaller or equal of
2607 GNUNET_assert(sum <= packetsize);
2608 if (sum == packetsize)
2613 GNUNET_ERROR_TYPE_DEBUG,
2614 "check_rec_finished_msg: A message for endpoint %p is complete\n",
2615 rx_message->endpoint);
2620 //copy fragments together
2621 //msg = GNUNET_malloc(packetsize);
2622 rx_frag = rx_message->frag_head;
2624 /*while (rx_frag != NULL)
2626 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2627 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2628 aktnum += rx_frag->size;
2629 rx_frag = rx_frag->next;
2632 while (rx_frag != NULL)
2634 if (rx_frag->next != NULL)
2636 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2637 session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
2642 //if it is the last fragment just kill all leftover
2643 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2644 session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
2647 rx_frag = rx_frag->next;
2649 session_light->macendpoint->message_id_backlog[session_light->macendpoint->message_id_backlog_pos]
2650 = rx_message->message_id_in;
2651 session_light->macendpoint->message_id_backlog_pos
2652 = (session_light->macendpoint->message_id_backlog_pos + 1)
2653 % MESSAGE_ID_BACKLOG_SIZE;
2654 free_receive_message(plugin, rx_message);
2655 //call wlan_process_helper to process the message
2656 //wlan_data_message_handler(plugin, session_light,
2657 // (struct GNUNET_MessageHeader*) msg);
2658 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2668 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2671 GNUNET_assert(client != NULL);
2672 GNUNET_assert(cls != NULL);
2673 struct Session * session = (struct Session *) client;
2674 struct Plugin * plugin = (struct Plugin *) cls;
2676 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2677 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2678 distance[0].value = htonl(1);
2679 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2680 distance[1].value = htonl(0);
2683 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2684 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2685 wlan_plugin_address_to_string(NULL, session->mac->addr.mac, 6),
2689 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2690 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2691 (const char*) &session->mac->addr, sizeof(session->mac->addr));
2695 * function to add an ack to send it for a received fragment
2696 * @param plugin pointer to the global plugin structure
2697 * @param endpoint pointer to the MacEndpoint this ack belongs to
2698 * @param bitfield bitfield to send
2699 * @param fh pointer to the fragmentation header which we would like to acknolage
2703 add_ack_for_send(struct Plugin * plugin, struct MacEndpoint * endpoint,
2704 uint64_t bitfield, struct FragmentationHeader * fh)
2706 struct AckSendQueue * ack;
2708 GNUNET_assert(plugin != NULL);
2709 GNUNET_assert(endpoint != NULL);
2710 GNUNET_assert(fh != NULL);
2712 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2713 ack->fragments_field = bitfield;
2714 ack->message_id = ntohl(fh->message_id);
2715 ack->endpoint = endpoint;
2717 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2718 plugin->ack_send_queue_tail, ack);
2723 * function to get the receive message from the message id and the session
2724 * @param plugin pointer to the plugin struct
2725 * @param endpoint MacEndpoint this fragment belongs to
2726 * @param message_id id of the message
2729 /*struct Receive_Message_Queue *
2730 get_receive_message(struct Plugin * plugin, struct MacEndpoint * endpoint,
2731 uint32_t message_id)
2733 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2734 while (rec_message != NULL)
2736 if ((rec_message->message_id_in == message_id) && (rec_message->endpoint
2741 rec_message = rec_message->next;
2747 * function to insert a received fragment into the right fragment queue of the right message
2748 * @param plugin pointer to the plugin struct
2749 * @param session_light pointer to the session_light struct of this message
2750 * @param fh pointer to the header of the fragment
2751 * @return new fragment bitfield for the message
2755 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2756 struct Session_light * session_light, struct FragmentationHeader * fh,
2757 const struct Radiotap_rx * rxinfo)
2759 struct Receive_Fragment_Queue * rx_frag = NULL;
2760 struct Receive_Message_Queue * rx_message;
2761 struct MacEndpoint * endpoint = session_light->macendpoint;
2762 const char * tempmsg = (char*) &fh[1];
2763 uint64_t retval = 0;
2766 //TODO fragments do not timeout
2767 //check if message_id is right or it is a new msg
2768 GNUNET_assert(fh != NULL);
2770 //check for receive of old messages
2771 for (i = 0; i < MESSAGE_ID_BACKLOG_SIZE; i++)
2773 if (endpoint->message_id_backlog[i] == ntohl(fh->message_id))
2775 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2780 rx_message = get_receive_message(plugin, endpoint, ntohl(fh->message_id));
2782 if (rx_message == NULL)
2784 if (endpoint->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2786 check_receive_message_timeouts(plugin);
2789 if (endpoint->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2792 //new message incoming
2793 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2794 rx_message->message_id_in = ntohl(fh->message_id);
2795 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2796 rx_message->endpoint = endpoint;
2797 rx_message->received_fragments = 0;
2799 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2801 endpoint->fragment_messages_in_count++;
2802 plugin->pending_receive_messages++;
2806 GNUNET_ERROR_TYPE_DEBUG,
2807 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2808 rx_message->message_id_in,
2809 rx_message->endpoint->fragment_messages_in_count,
2810 plugin->pending_receive_messages);
2817 GNUNET_ERROR_TYPE_INFO,
2818 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2819 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2825 rx_message->timeout = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(),
2826 MESSAGE_IN_TIMEOUT);
2828 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2832 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2833 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2834 rx_frag->size = ntohs(fh->header.size)
2835 - sizeof(struct FragmentationHeader);
2836 rx_frag->num = ntohs(fh->fragment_off_or_num);
2837 rx_frag->msg = (char*) &(rx_frag[1]);
2838 //copy msg to buffer
2839 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2840 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2841 insert_fragment_in_queue(rx_message, rx_frag);
2843 retval = rx_message->received_fragments;
2847 GNUNET_ERROR_TYPE_DEBUG,
2848 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, endpoint %p\n",
2849 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2850 rx_message->received_fragments, rx_message->endpoint);
2853 check_rx_finished_msg(plugin, session_light, rx_message);
2857 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2858 retval = rx_message->received_fragments;
2866 * Function used for to process the data received from the wlan interface
2868 * @param cls the plugin handle
2869 * @param session_light FIXME: document
2870 * @param hdr hdr of the GNUNET_MessageHeader
2873 wlan_data_helper(void *cls, struct Session_light * session_light,
2874 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2876 struct Plugin *plugin = cls;
2878 struct FragmentationHeader * fh;
2879 struct FragmentationAckHeader * fah;
2880 struct FragmentMessage * fm;
2882 const char * tempmsg;
2884 uint64_t fragment_bitfield = 0;
2887 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2890 //TODO better DOS protection, error handling
2891 //TODO test first than create session
2892 GNUNET_assert(session_light != NULL);
2896 GNUNET_ERROR_TYPE_DEBUG,
2897 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2899 wlan_plugin_address_to_string(NULL, session_light->addr.mac, 6));
2902 if (session_light->macendpoint == NULL)
2904 session_light->macendpoint = get_macendpoint(plugin,
2905 &session_light->addr, GNUNET_NO);
2907 GNUNET_assert(GNUNET_HELLO_get_id(
2908 (const struct GNUNET_HELLO_Message *) &hdr[1],
2909 &(session_light->session->target) ) != GNUNET_SYSERR);
2915 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2918 GNUNET_assert(session_light != NULL);
2919 if (session_light->macendpoint == NULL)
2921 session_light->macendpoint = get_macendpoint(plugin,
2922 &session_light->addr, GNUNET_NO);
2925 fh = (struct FragmentationHeader *) hdr;
2926 tempmsg = (char*) &fh[1];
2930 GNUNET_ERROR_TYPE_DEBUG,
2931 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2932 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num),
2934 wlan_plugin_address_to_string(NULL, session_light->addr.mac, 6));
2937 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2939 //wrong crc, dispose message
2940 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2944 //if in the session list
2945 if (session_light->macendpoint != NULL)
2947 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2948 session_light, fh, rxinfo);
2954 GNUNET_ERROR_TYPE_INFO,
2955 "WLAN client not in session list, fragment num %u, message id %u\n",
2956 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2958 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
2959 tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
2960 GNUNET_YES, GNUNET_NO);
2961 //wlan_data_message_handler(plugin, session_light,
2962 // (struct GNUNET_MessageHeader *) tempmsg);
2963 //test if a session was created
2964 if (session_light->session == NULL)
2968 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2971 add_ack_for_send(plugin, session_light->macendpoint, fragment_bitfield,
2973 set_next_send(plugin);
2979 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2984 GNUNET_ERROR_TYPE_DEBUG,
2985 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2987 wlan_plugin_address_to_string(NULL, session_light->addr.mac, 6));
2990 GNUNET_assert(session_light != NULL);
2991 if (session_light->macendpoint == NULL)
2993 session_light->macendpoint = get_macendpoint(plugin,
2994 &session_light->addr, GNUNET_NO);
2997 fah = (struct FragmentationAckHeader *) hdr;
2998 fm = get_fragment_message_from_endpoint_and_id(plugin,
2999 session_light->macendpoint, ntohl(fah->message_id));
3004 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
3005 fah->fragment_field);
3006 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
3008 #if DEBUG_wlan_retransmission
3009 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
3010 fm->message_id_out, fm->ack_bitfield);
3012 check_finished_fragment(plugin, fm);
3013 set_next_send(plugin);
3018 //GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3019 // "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
3020 // fah->message_id));
3029 GNUNET_ERROR_TYPE_INFO,
3030 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
3031 ntohs(hdr->type), ntohs(hdr->size));
3037 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3038 "Helper finished\n");
3045 macprinter(const u_int8_t * mac)
3047 static char macstr[20];
3049 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
3050 mac[2], mac[3], mac[4], mac[5]);
3055 * Function used for to process the data from the suid process
3057 * @param cls the plugin handle
3058 * @param client client that send the data (not used)
3059 * @param hdr header of the GNUNET_MessageHeader
3062 wlan_process_helper(void *cls, void *client,
3063 const struct GNUNET_MessageHeader *hdr)
3065 struct Plugin *plugin = cls;
3066 struct ieee80211_frame * wlanIeeeHeader = NULL;
3067 struct Session_light * session_light = NULL;
3068 struct Radiotap_rx * rxinfo;
3069 const struct GNUNET_MessageHeader * temp_hdr = NULL;
3074 switch (ntohs(hdr->type))
3076 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
3079 GNUNET_ERROR_TYPE_DEBUG,
3080 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
3084 //call wlan_process_helper with the message inside, later with wlan: analyze signal
3085 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
3086 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
3090 GNUNET_ERROR_TYPE_DEBUG,
3091 "Size of packet is too small; size: %u min size: %u\n",
3093 sizeof(struct ieee80211_frame)
3094 + sizeof(struct GNUNET_MessageHeader));
3097 /* FIXME: restart SUID process */
3100 rxinfo = (struct Radiotap_rx *) &hdr[1];
3101 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
3103 //process only if it is an broadcast or for this computer both with the gnunet bssid
3106 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
3107 sizeof(struct MacAddress)) == 0)
3109 //check for broadcast or mac
3110 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
3111 sizeof(struct MacAddress) == 0) || memcmp(
3112 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
3113 sizeof(struct MacAddress)) == 0)
3116 // process the inner data
3119 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
3120 - sizeof(struct GNUNET_MessageHeader)
3121 - sizeof(struct Radiotap_rx);
3123 session_light = GNUNET_malloc(sizeof(struct Session_light));
3124 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
3125 sizeof(struct MacAddress));
3126 //session_light->session = search_session(plugin,session_light->addr);
3129 while (pos < datasize)
3131 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
3134 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
3135 pos += ntohs(temp_hdr->size);
3140 GNUNET_free(session_light);
3145 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3146 "Func wlan_process_helper got wrong MAC: %s\n",
3147 macprinter(wlanIeeeHeader->i_addr1));
3154 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3155 "Func wlan_process_helper got wrong BSSID: %s\n",
3156 macprinter(wlanIeeeHeader->i_addr2));
3160 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
3161 //TODO more control messages
3162 //TODO use struct wlan_helper_control
3163 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
3166 /* FIXME: restart SUID process */
3169 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
3172 GNUNET_ERROR_TYPE_DEBUG,
3173 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
3174 wlan_plugin_address_to_string(cls, &plugin->mac_address,
3175 sizeof(struct MacAddress)));
3177 plugin->env->notify_address(plugin->env->cls, GNUNET_YES,
3178 &plugin->mac_address, sizeof(struct MacAddress));
3187 * We have been notified that wlan-helper has written something to stdout.
3188 * Handle the output, then reschedule this function to be called again once
3189 * more is available.
3191 * @param cls the plugin handle
3192 * @param tc the scheduling context
3195 wlan_plugin_helper_read(void *cls,
3196 const struct GNUNET_SCHEDULER_TaskContext *tc)
3198 struct Plugin *plugin = cls;
3199 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3201 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
3204 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
3207 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
3212 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3213 _("Finished reading from wlan-helper stdout with code: %d\n"),
3218 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
3219 GNUNET_NO, GNUNET_NO);
3221 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3222 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3223 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3224 &wlan_plugin_helper_read, plugin);
3228 * Start the gnunet-wlan-helper process.
3230 * @param plugin the transport plugin
3231 * @param testmode should we use the dummy driver for testing?
3232 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
3235 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
3237 const char * filenamehw = "gnunet-transport-wlan-helper";
3238 const char * filenameloopback = "gnunet-transport-wlan-helper-dummy";
3239 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
3240 if (plugin->server_stdout == NULL)
3241 return GNUNET_SYSERR;
3243 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
3244 if (plugin->server_stdin == NULL)
3245 return GNUNET_SYSERR;
3247 /* Start the server process */
3253 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3254 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filenamehw,
3255 plugin->interface, testmode);
3258 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3259 plugin->server_stdout, filenamehw, filenamehw, plugin->interface,
3262 else if (testmode == 1)
3266 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3267 "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n",
3268 filenameloopback, plugin->interface, testmode);
3271 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3272 plugin->server_stdout, filenameloopback, filenameloopback, "1", NULL);
3274 else if (testmode == 2)
3277 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3278 "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n",
3279 filenameloopback, plugin->interface, testmode);
3281 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3282 plugin->server_stdout, filenameloopback, filenameloopback, "2", NULL);
3284 if (plugin->server_proc == NULL)
3287 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3288 "Failed to start gnunet-wlan-helper process\n");
3290 return GNUNET_SYSERR;
3293 /* Close the write end of the read pipe */
3294 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
3296 /* Close the read end of the write pipe */
3297 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
3299 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
3300 GNUNET_DISK_PIPE_END_READ);
3301 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
3302 GNUNET_DISK_PIPE_END_WRITE);
3304 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3307 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3308 "Adding server_read_task for the wlan-helper\n");
3311 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3312 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3313 &wlan_plugin_helper_read, plugin);
3319 * Exit point from the plugin.
3320 * @param cls pointer to the api struct
3325 libgnunet_plugin_transport_wlan_done(void *cls)
3327 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3328 struct Plugin *plugin = api->cls;
3329 struct MacEndpoint * endpoint = plugin->mac_head;
3330 struct MacEndpoint * endpoint_next;
3331 struct FragmentMessage * fm;
3334 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3335 "libgnunet_plugin_transport_wlan_done started\n");
3338 GNUNET_DISK_pipe_close(plugin->server_stdout);
3339 GNUNET_DISK_pipe_close(plugin->server_stdin);
3340 GNUNET_OS_process_kill(plugin->server_proc, 9);
3341 GNUNET_OS_process_close(plugin->server_proc);
3343 GNUNET_assert (cls !=NULL);
3345 while (endpoint != NULL)
3347 endpoint_next = endpoint->next;
3348 free_macendpoint(plugin, endpoint);
3349 endpoint = endpoint_next;
3352 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
3354 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
3355 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3357 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
3359 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
3360 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3362 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
3364 GNUNET_SCHEDULER_cancel(plugin->server_read_task);
3365 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3368 if (plugin->suid_tokenizer != NULL)
3369 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
3371 if (plugin->data_tokenizer != NULL)
3372 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3374 if (plugin->fragment_tokenizer != NULL)
3375 GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
3377 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3378 plugin->pending_Fragment_Messages);
3382 free_fragment_message(plugin, fm);
3383 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3384 plugin->pending_Fragment_Messages);
3387 GNUNET_free_non_null(plugin->interface);
3388 GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
3389 GNUNET_free (plugin);
3395 * Entry point for the plugin.
3397 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3398 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3401 libgnunet_plugin_transport_wlan_init(void *cls)
3403 //struct GNUNET_SERVICE_Context *service;
3404 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3405 struct GNUNET_TRANSPORT_PluginFunctions *api;
3406 struct Plugin *plugin;
3407 static unsigned long long testmode = 0;
3409 GNUNET_assert(cls !=NULL);
3411 plugin = GNUNET_malloc (sizeof (struct Plugin));
3413 plugin->pendingsessions = 0;
3414 plugin->mac_count = 0;
3415 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3416 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3417 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3418 plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
3419 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3421 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3424 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3425 plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
3426 &wlan_data_message_handler, plugin);
3428 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3429 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3431 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3433 api->send = &wlan_plugin_send;
3434 api->disconnect = &wlan_plugin_disconnect;
3435 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3436 api->check_address = &wlan_plugin_address_suggested;
3437 api->address_to_string = &wlan_plugin_address_to_string;
3440 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3442 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3443 "transport-wlan", "TESTMODE", &testmode))
3444 testmode = 0; //default value
3447 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3449 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3450 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3452 libgnunet_plugin_transport_wlan_done(api);
3458 set_next_beacon_time(plugin);
3460 wlan_transport_start_wlan_helper(plugin, testmode);
3463 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3469 /* end of plugin_transport_wlan.c */