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
54 #define FRAGMENT_QUEUE_SIZE 10
55 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
57 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
59 #define MESSAGES_IN_QUEUE_SIZE 10
60 #define MESSAGES_IN_QUEUE_PER_SESSION 1
62 #define HALLO_BEACON_SCALING_FACTOR 900
64 #define DEBUG_wlan GNUNET_NO
65 #define DEBUG_wlan_retransmission GNUNET_NO
66 #define DEBUG_wlan_ip_udp_packets_on_air GNUNET_NO
68 #define MESSAGE_LENGHT_UNKNOWN -1
69 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
72 * After how long do we expire an address that we
73 * learned from another peer if it is not reconfirmed
76 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
78 #define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
80 #define IEEE80211_FC0_VERSION_MASK 0x03
81 #define IEEE80211_FC0_VERSION_SHIFT 0
82 #define IEEE80211_FC0_VERSION_0 0x00
83 #define IEEE80211_FC0_TYPE_MASK 0x0c
84 #define IEEE80211_FC0_TYPE_SHIFT 2
85 #define IEEE80211_FC0_TYPE_MGT 0x00
86 #define IEEE80211_FC0_TYPE_CTL 0x04
87 #define IEEE80211_FC0_TYPE_DATA 0x08
90 * Structure of an internet header, naked of options.
94 #if __BYTE_ORDER == __LITTLE_ENDIAN
95 unsigned int ip_hl:4; /* header length */
96 unsigned int ip_v:4; /* version */
98 #if __BYTE_ORDER == __BIG_ENDIAN
99 unsigned int ip_v:4; /* version */
100 unsigned int ip_hl:4; /* header length */
102 u_int8_t ip_tos; /* type of service */
103 u_short ip_len; /* total length */
104 u_short ip_id; /* identification */
105 u_short ip_off; /* fragment offset field */
106 #define IP_RF 0x8000 /* reserved fragment flag */
107 #define IP_DF 0x4000 /* dont fragment flag */
108 #define IP_MF 0x2000 /* more fragments flag */
109 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
110 u_int8_t ip_ttl; /* time to live */
111 u_int8_t ip_p; /* protocol */
112 u_short ip_sum; /* checksum */
113 struct in_addr ip_src, ip_dst; /* source and dest address */
125 * generic definitions for IEEE 802.11 frames
127 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];
134 #if DEBUG_wlan_ip_udp_packets_on_air
141 * Initial handshake message for a session.
143 struct WelcomeMessage
146 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
148 struct GNUNET_MessageHeader header;
151 * Identit*mac_y of the node connecting (TCP client)
153 struct GNUNET_PeerIdentity clientIdentity;
158 * Encapsulation of all of the state of the plugin.
165 struct GNUNET_TRANSPORT_PluginEnvironment *env;
168 * List of open sessions. head
170 struct Sessionqueue *sessions;
173 * List of open sessions. tail
175 struct Sessionqueue *sessions_tail;
180 unsigned int session_count;
183 * encapsulation of data from the local wlan helper program
185 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
188 * encapsulation of packets received from the wlan helper
190 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
192 * encapsulation of packets received
194 struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
197 * stdout pipe handle for the gnunet-wlan-helper process
199 struct GNUNET_DISK_PipeHandle *server_stdout;
202 * stdout file handle for the gnunet-wlan-helper process
204 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
207 * stdin pipe handle for the gnunet-wlan-helper process
209 struct GNUNET_DISK_PipeHandle *server_stdin;
212 * stdin file handle for the gnunet-wlan-helper process
214 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
217 * ID of the gnunet-wlan-server std read task
219 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
222 * ID of the gnunet-wlan-server std read task
224 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
227 * ID of the delay task for writing
229 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
232 * The process id of the wlan process
234 struct GNUNET_OS_Process *server_proc;
237 * The interface of the wlan card given to us by the user.
242 * The mac_address of the wlan card given to us by the helper.
244 struct MacAddress mac_address;
247 * Sessions currently pending for transmission
248 * to this peer, if any.
250 struct Sessionqueue * pending_Sessions_head;
253 * Sessions currently pending for transmission
254 * to this peer (tail), if any.
256 struct Sessionqueue * pending_Sessions_tail;
259 * number of pending sessions
261 unsigned int pendingsessions;
264 * Messages in the fragmentation queue, head
266 struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
269 * Messages in the in Queue, head
271 struct Receive_Message_Queue * receive_messages_head;
274 * Messages in the in Queue, tail
276 struct Receive_Message_Queue * receive_messages_teil;
279 * number of messages in the in queue
281 unsigned int pending_receive_messages;
284 * time of the next "hello-beacon"
286 struct GNUNET_TIME_Absolute beacon_time;
289 * queue to send acks for received fragments (head)
291 struct AckSendQueue * ack_send_queue_head;
294 * queue to send acks for received fragments (tail)
296 struct AckSendQueue * ack_send_queue_tail;
301 * Struct to store data if file write did not accept the whole packet
305 struct Plugin * plugin;
307 struct GNUNET_MessageHeader * msgstart;
312 * Queue of sessions, for the general session queue and the pending session queue
317 struct Sessionqueue * next;
318 struct Sessionqueue * prev;
319 struct Session * content;
323 * Queue for the fragments received
326 struct Receive_Fragment_Queue
328 struct Receive_Fragment_Queue * next;
329 struct Receive_Fragment_Queue * prev;
333 struct Radiotap_rx rxinfo;
337 struct Session_id_fragment_triple
339 struct Session * session;
341 struct FragmentMessage * fm;
345 struct Plugin_Session_pair
347 struct Plugin * plugin;
348 struct Session * session;
352 * Queue for the fragments received
354 struct Receive_Message_Queue
356 struct Receive_Message_Queue * next;
358 struct Receive_Message_Queue * prev;
361 * current number for message incoming, to distinguish between the messages
363 uint32_t message_id_in;
366 * size of the message received,
367 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
368 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
373 * Sorted queue with the fragments received; head
376 struct Receive_Fragment_Queue * frag_head;
379 * Sorted queue with the fragments received; tail
382 struct Receive_Fragment_Queue * frag_tail;
385 * Session this fragment belongs to
388 struct Session * session;
391 * Timeout value for the pending message.
393 struct GNUNET_TIME_Absolute timeout;
396 * Bitfield of received fragments
399 uint64_t received_fragments;
403 * Information kept for each message that is yet to
406 struct PendingMessage
410 * The pending message
415 * Size of the message
420 * Continuation function to call once the message
421 * has been sent. Can be NULL if there is no
422 * continuation to call.
424 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
427 * Cls for transmit_cont
429 void * transmit_cont_cls;
432 * Timeout value for the pending message.
434 struct GNUNET_TIME_Absolute timeout;
439 * Queue for acks to send for fragments recived
445 * next ack in the ack send queue
447 struct AckSendQueue * next;
449 * previous ack in the ack send queue
451 struct AckSendQueue * prev;
453 * pointer to the session this ack belongs to
455 struct Session * session;
457 * ID of message, to distinguish between the messages, picked randomly.
462 * Bit field for received fragments
464 uint64_t fragments_field;
469 * Session infos gathered from a messages
475 * the session this message belongs to
477 struct Session * session;
481 struct MacAddress addr;
485 * Session handle for connections.
493 struct SessionHeader header;
496 * Pointer to the global plugin struct.
498 struct Plugin *plugin;
501 * Message currently pending for transmission
502 * to this peer, if any.
504 struct PendingMessage *pending_message;
507 * Message currently pending for transmission
508 * to this peer, if any.
510 struct PendingMessage *pending_message2;
513 * To whom are we talking to (set to our identity
514 * if we are still waiting for the welcome message)
516 struct GNUNET_PeerIdentity target;
521 struct MacAddress addr;
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
533 struct GNUNET_TIME_Absolute last_activity;
536 * count of messages in the fragment out queue for this session
539 int fragment_messages_out_count;
542 * count of messages in the fragment in queue for this session
545 int fragment_messages_in_count;
555 * Struct for Messages in the fragment queue
558 struct FragmentMessage
561 * heap pointer of this message
563 struct GNUNET_CONTAINER_HeapNode * node;
566 * Session this message belongs to
569 struct Session *session;
572 * This is a doubly-linked list.
574 struct FragmentMessage *next;
577 * This is a doubly-linked list.
579 struct FragmentMessage *prev;
582 * The pending message
587 * 0 if not in ack queue
594 * Timeout value for the pending message.
596 struct GNUNET_TIME_Absolute timeout;
599 * Timeout value for the pending fragments.
600 * Stores the time when the next msg fragment ack has to be received
602 struct GNUNET_TIME_Absolute next_ack;
605 * bitfield with all acks received for this message
607 uint64_t ack_bitfield;
610 * Size of the message
615 * pos / next fragment number in the message, for fragmentation/segmentation,
616 * some acks can be missing but there is still time
618 uint32_t message_pos;
621 * current number for message outgoing, to distinguish between the messages
623 uint32_t message_id_out;
627 * Header for messages which need fragmentation
629 struct FragmentationAckHeader
632 struct GNUNET_MessageHeader header;
635 * ID of message, to distinguish between the messages, picked randomly.
637 uint32_t message_id GNUNET_PACKED;
640 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
642 uint64_t fragment_field GNUNET_PACKED;
647 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
650 * Generates a nice hexdump of a memory area.
652 * \param mem pointer to memory to dump
653 * \param length how many bytes to dump
655 void hexdump(void *mem, unsigned length)
658 char *src = (char*)mem;
661 "dumping %u bytes from %p\r\n"
662 " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\r\n"
668 for (i=0; i<length; i+=16, src+=16) {
671 t += sprintf(t, "%04x: ", i);
672 for ( j=0; j<16; j++) {
674 t += sprintf(t, "%02X", src[j] & 0xff);
676 t += sprintf(t, " ");
677 t += sprintf(t, j%2 ? " " : "-");
680 t += sprintf(t, " ");
681 for (j=0; j<16; j++) {
683 if (isprint((unsigned char)src[j]))
684 t += sprintf(t, "%c", src[j]);
686 t += sprintf(t, ".");
688 t += sprintf(t, " ");
692 t += sprintf(t, "\r\n");
698 * Sets a bit active in the bitArray. Increment bit-specific
699 * usage counter on disk only if below 4bit max (==15).
701 * @param bitArray memory area to set the bit in
702 * @param bitIdx which bit to set
705 setBit(char *bitArray, unsigned int bitIdx)
708 unsigned int targetBit;
710 arraySlot = bitIdx / 8;
711 targetBit = (1L << (bitIdx % 8));
712 bitArray[arraySlot] |= targetBit;
716 * Checks if a bit is active in the bitArray
718 * @param bitArray memory area to set the bit in
719 * @param bitIdx which bit to test
720 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
723 testBit(char *bitArray, unsigned int bitIdx)
726 unsigned int targetBit;
729 targetBit = (1L << (bitIdx % 8));
730 if (bitArray[slot] & targetBit)
736 * get the next message number, at the moment just a random one
737 * @return returns the next valid message-number for sending packets
740 get_next_message_id()
742 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
746 * search for a session with the addr
748 * @param plugin pointer to the plugin struct
749 * @param addr pointer to the mac address of the peer
750 * @return returns the session
752 static struct Session *
753 search_session(struct Plugin *plugin, const struct MacAddress *addr)
755 struct Sessionqueue * queue = plugin->sessions;
757 while (queue != NULL)
759 GNUNET_assert (queue->content != NULL);
760 if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
761 return queue->content; /* session found */
768 * Function called for a quick conversion of the binary address to
769 * a numeric address. Note that the caller must not free the
770 * address and that the next call to this function is allowed
771 * to override the address again.
774 * @param addr binary address
775 * @param addrlen length of the address
776 * @return string representing the same address
779 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
782 const struct MacAddress *mac;
784 if (addrlen != sizeof(struct MacAddress))
790 GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
791 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
792 mac->mac[4], mac->mac[5]);
797 * create a new session
799 * @param plugin pointer to the plugin struct
800 * @param addr pointer to the mac address of the peer
801 * @return returns the session
804 static struct Session *
805 create_session(struct Plugin *plugin, const struct MacAddress * addr)
807 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
809 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
811 queue->content = GNUNET_malloc (sizeof (struct Session));
812 queue->content->plugin = plugin;
813 queue->content->addr = *addr;
814 queue->content->fragment_messages_out_count = 0;
815 queue->content->fragment_messages_in_count = 0;
817 plugin->session_count++;
820 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
821 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
824 return queue->content;
828 * Get session from address, create if no session exists
830 * @param plugin pointer to the plugin struct
831 * @param addr pointer to the mac address of the peer
832 * @return returns the session
834 static struct Session *
835 get_session(struct Plugin *plugin, const struct MacAddress *addr)
837 struct Session * session = search_session(plugin, addr);
840 return create_session(plugin, addr);
844 * Queue the session to send data
845 * checks if there is a message pending
846 * checks if this session is not allready in the queue
847 * @param plugin pointer to the plugin
848 * @param session pointer to the session to add
851 queue_session(struct Plugin *plugin, struct Session * session)
853 struct Sessionqueue * queue = plugin->pending_Sessions_head;
855 if (session->pending_message != NULL)
857 while (queue != NULL)
859 // content is never NULL
860 GNUNET_assert (queue->content != NULL);
861 // is session already in queue?
862 if (session == queue->content)
870 // Session is not in the queue
872 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
873 queue->content = session;
876 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
877 plugin->pending_Sessions_tail, queue);
878 plugin->pendingsessions++;
884 * Function to schedule the write task, executed after a delay
885 * @param cls pointer to the plugin struct
886 * @param tc GNUNET_SCHEDULER_TaskContext pointer
889 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
891 struct Plugin * plugin = cls;
892 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
894 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
897 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
898 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
900 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
901 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
902 &do_transmit, plugin);
907 * Function to calculate the time of the next periodic "hello-beacon"
908 * @param plugin pointer to the plugin struct
912 set_next_beacon_time(struct Plugin * const plugin)
914 //under 10 known peers: once a second
915 if (plugin->session_count < 10)
917 plugin->beacon_time = GNUNET_TIME_absolute_add(
918 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
919 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
921 //under 30 known peers: every 10 seconds
922 else if (plugin->session_count < 30)
924 plugin->beacon_time = GNUNET_TIME_absolute_add(
925 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
926 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
928 //over 30 known peers: once a minute
931 plugin->beacon_time = GNUNET_TIME_absolute_add(
932 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
933 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
938 * Function to get the timeout value for acks for this session
939 * @param fm pointer to the FragmentMessage to get the next timeout
940 * @return time until the next ack should be received, in GNUNET_TIME_Relative
942 static struct GNUNET_TIME_Relative
943 get_ack_timeout(struct FragmentMessage * fm)
945 return FRAGMENT_TIMEOUT;
949 * Function to set the timer for the next timeout of the fragment queue
950 * @param plugin the handle to the plugin struct
954 set_next_send(struct Plugin * const plugin)
956 struct FragmentMessage * fm;
957 struct GNUNET_TIME_Relative next_send;
958 struct GNUNET_TIME_Absolute next_send_tmp;
961 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
963 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
964 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
967 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
969 //check if some acks are in the queue
970 if (plugin->ack_send_queue_head != NULL)
972 next_send = GNUNET_TIME_UNIT_ZERO;
975 //check if there are some fragments in the queue
978 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
981 next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
983 next_send = GNUNET_TIME_relative_min(next_send,
984 GNUNET_TIME_absolute_get_remaining(next_send_tmp));
991 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
992 next_send.rel_value);
996 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
998 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1000 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1001 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1002 &do_transmit, plugin);
1007 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1008 &delay_fragment_task, plugin);
1013 * Function to get the next queued Session, removes the session from the queue
1014 * @param plugin pointer to the plugin struct
1015 * @return pointer to the session found, returns NULL if there is now session in the queue
1017 static struct Session *
1018 get_next_queue_session(struct Plugin * plugin)
1020 struct Session * session;
1021 struct Sessionqueue * sessionqueue;
1022 struct Sessionqueue * sessionqueue_alt;
1023 struct PendingMessage * pm;
1024 sessionqueue = plugin->pending_Sessions_head;
1026 while (sessionqueue != NULL)
1028 session = sessionqueue->content;
1030 GNUNET_assert(session != NULL);
1031 pm = session->pending_message;
1036 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1037 "pending message is empty, should not happen. session %p\n",
1042 GNUNET_assert(pm != NULL);
1044 //check for message timeout
1045 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1047 //check if session has no message in the fragment queue
1048 if (session->fragment_messages_out_count
1049 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1051 plugin->pendingsessions--;
1052 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1053 plugin->pending_Sessions_tail, sessionqueue);
1054 GNUNET_free(sessionqueue);
1060 sessionqueue = sessionqueue->next;
1066 session->pending_message = session->pending_message2;
1067 session->pending_message2 = NULL;
1069 //call the cont func that it did not work
1070 if (pm->transmit_cont != NULL)
1071 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1073 GNUNET_free(pm->msg);
1076 if (session->pending_message == NULL)
1078 sessionqueue_alt = sessionqueue;
1079 sessionqueue = sessionqueue->next;
1080 plugin->pendingsessions--;
1081 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1082 plugin->pending_Sessions_tail, sessionqueue_alt);
1084 GNUNET_free(sessionqueue_alt);
1094 * frees the space of a message in the fragment queue (send queue)
1095 * @param plugin the plugin struct
1096 * @param fm message to free
1099 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1101 struct Session * session = fm->session;
1105 (session->fragment_messages_out_count)--;
1106 GNUNET_free_non_null(fm->msg);
1107 GNUNET_CONTAINER_heap_remove_node(fm->node);
1110 queue_session(plugin, session);
1112 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1113 "free pending fragment messages, pending messages remaining %u\n",
1114 GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
1120 * Function to check if there is some space in the fragment queue
1121 * inserts a message if space is available
1122 * @param plugin the plugin struct
1126 check_fragment_queue(struct Plugin * plugin)
1128 struct Session * session;
1129 struct FragmentMessage * fm;
1130 struct GNUNET_PeerIdentity pid;
1132 struct PendingMessage * pm;
1134 if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1135 < FRAGMENT_QUEUE_SIZE)
1137 session = get_next_queue_session(plugin);
1138 if (session != NULL)
1140 pm = session->pending_message;
1141 session->pending_message = NULL;
1142 session->fragment_messages_out_count++;
1143 GNUNET_assert(pm != NULL);
1145 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1146 fm->message_size = pm->message_size;
1148 fm->session = session;
1149 fm->timeout.abs_value = pm->timeout.abs_value;
1150 fm->message_pos = 0;
1151 fm->next_ack = GNUNET_TIME_absolute_get();
1152 fm->message_id_out = get_next_message_id();
1153 fm->ack_bitfield = 0;
1154 fm->node = GNUNET_CONTAINER_heap_insert(
1155 plugin->pending_Fragment_Messages, fm,
1156 GNUNET_TIME_absolute_get().abs_value);
1158 GNUNET_assert(session !=NULL);
1160 if (pm->transmit_cont != NULL)
1162 pid = session->target;
1163 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1165 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1166 "called pm->transmit_cont for %p\n", session);
1172 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1173 "no pm->transmit_cont for %p\n", session);
1178 if (session->pending_message2 != NULL)
1180 session->pending_message = session->pending_message2;
1181 session->pending_message2 = NULL;
1183 queue_session(plugin, session);
1189 //check if timeout changed
1190 set_next_send(plugin);
1194 * Funktion to check if all fragments where send and the acks received
1195 * frees the space if finished
1196 * @param plugin the plugin struct
1197 * @param fm the message to check
1200 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1202 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1203 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1204 - sizeof(struct FragmentationHeader)));
1205 uint64_t tmpfield = UINT64_MAX;
1206 tmpfield = tmpfield >> maxack;
1210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1211 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1212 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1215 if (fm->ack_bitfield == tmpfield)
1218 #if DEBUG_wlan_retransmission
1219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1220 "Finished sending and got all acks; message_id %u\n",
1221 fm->message_id_out);
1224 free_fragment_message(plugin, fm);
1226 check_fragment_queue(plugin);
1232 * Function to set the next fragment number
1233 * @param fm use this FragmentMessage
1237 set_next_message_fragment_pos(struct Plugin * plugin,
1238 struct FragmentMessage * fm)
1243 //check if retransmit is needed
1244 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1247 // be positive and try again later :-D
1248 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1249 // find first missing fragment
1251 fm->message_pos = 0;
1253 GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1256 #if DEBUG_wlan_retransmission
1257 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1258 "Retransmit; message_id %u; fragment number %i, size: %u\n",
1259 fm->message_id_out, fm->message_pos, fm->message_size);
1263 //test if ack 0 (or X) was already received
1264 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1273 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1274 struct Radiotap_Send * header)
1277 if (session != NULL)
1279 header->rate = session->rate;
1280 header->tx_power = session->tx_power;
1281 header->antenna = session->antenna;
1286 header->tx_power = 0;
1287 header->antenna = 0;
1294 * function to generate the wlan hardware header for one packet
1295 * @param Header address to write the header to
1296 * @param to_mac_addr address of the recipient
1297 * @param plugin pointer to the plugin struct
1298 * @return GNUNET_YES if there was no error
1301 getWlanHeader(struct ieee80211_frame * Header,
1302 const struct MacAddress * to_mac_addr, struct Plugin * plugin,
1306 const int rate = 11000000;
1308 Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
1309 Header->i_fc[1] = 0x00;
1310 memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1311 memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1312 memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
1314 tmp16 = (uint16_t*) Header->i_dur;
1315 *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
1317 #if DEBUG_wlan_ip_udp_packets_on_air
1321 Header->ip.ip_dst.s_addr = *((uint32_t*) &to_mac_addr->mac[2]);
1322 Header->ip.ip_src.s_addr = *((uint32_t*) &plugin->mac_address.mac[2]);
1323 Header->ip.ip_v = 4;
1324 Header->ip.ip_hl = 5;
1325 Header->ip.ip_p = 17;
1326 Header->ip.ip_ttl = 1;
1327 Header->ip.ip_len = htons(size + 8);
1328 Header->ip.ip_sum = 0;
1329 x =(uint16_t *) &Header->ip;
1330 count = sizeof(struct iph);
1332 /* This is the inner loop */
1333 crc += (unsigned short) * x++;
1336 /* Add left-over byte, if any */
1338 crc += * (unsigned char *) x;
1339 crc = (crc & 0xffff) + (crc >> 16);
1340 Header->ip.ip_sum = htons(~ (unsigned short) crc);
1343 Header->udp.len = htons(size - sizeof(struct ieee80211_frame));
1353 * @param msgbuf pointer tor the data
1354 * @param msgbuf_size size of the data
1356 * @return 32bit crc value
1360 getcrc32(const char *msgbuf, size_t msgbuf_size)
1363 return GNUNET_CRYPTO_crc32_n(msgbuf, msgbuf_size);;
1369 * @param msgbuf pointer tor the data
1370 * @param msgbuf_size size of the data
1372 * @return 16bit crc value
1376 getcrc16(const char *msgbuf, size_t msgbuf_size)
1378 //TODO calc some crc
1384 send_hello_beacon(struct Plugin * plugin)
1388 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1393 uint16_t hallo_size;
1394 struct GNUNET_MessageHeader * msgheader;
1395 struct ieee80211_frame * ieeewlanheader;
1396 struct Radiotap_Send * radioHeader;
1397 struct GNUNET_MessageHeader * msgheader2;
1399 hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1400 GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1401 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1402 + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1405 msgheader = GNUNET_malloc(size);
1406 msgheader->size = htons(size);
1407 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1409 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1410 getRadiotapHeader(plugin, NULL, radioHeader);
1411 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1412 getWlanHeader(ieeewlanheader, &bc_all_mac, plugin, size);
1414 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1415 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1416 + sizeof(struct GNUNET_MessageHeader));
1418 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1419 memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1421 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1423 if (bytes == GNUNET_SYSERR)
1425 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1426 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1427 errno, strerror(errno));
1430 GNUNET_assert(bytes != GNUNET_SYSERR);
1431 GNUNET_assert(bytes == size);
1432 GNUNET_free(msgheader);
1434 set_next_beacon_time(plugin);
1435 set_next_send(plugin);
1440 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1445 struct GNUNET_MessageHeader * msgheader;
1446 struct ieee80211_frame * ieeewlanheader;
1447 struct Radiotap_Send * radioHeader;
1448 struct FragmentationAckHeader * msgheader2;
1450 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1452 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1453 + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1456 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1457 "Sending ack for message_id %u with fragment field %u, size %u\n",
1458 ack->message_id, ack->fragments_field, size
1459 - sizeof(struct Radiotap_Send));
1462 msgheader = GNUNET_malloc(size);
1463 msgheader->size = htons(size);
1464 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1466 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1467 getRadiotapHeader(plugin, ack->session, radioHeader);
1468 ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1469 getWlanHeader(ieeewlanheader, &ack->session->addr, plugin, size);
1471 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1472 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1473 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1474 msgheader2->message_id = htonl(ack->message_id);
1475 msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1477 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1478 if (bytes == GNUNET_SYSERR)
1480 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1481 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1482 errno, strerror(errno));
1485 GNUNET_assert(bytes != GNUNET_SYSERR);
1486 GNUNET_assert(bytes == size);
1487 GNUNET_free(msgheader);
1488 set_next_send(plugin);
1493 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1495 struct Finish_send * finish = cls;
1496 struct Plugin * plugin;
1499 plugin = finish->plugin;
1500 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1502 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1504 GNUNET_free (finish->msgstart);
1505 GNUNET_free (finish);
1508 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1509 finish->msgheader, finish->size);
1510 GNUNET_assert (bytes != GNUNET_SYSERR);
1512 if (bytes != finish->size)
1514 finish->msgheader = finish->msgheader + bytes;
1515 finish->size = finish->size - bytes;
1516 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1517 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1518 &finish_sending, finish);
1522 GNUNET_free(finish->msgstart);
1523 GNUNET_free(finish);
1524 set_next_send(plugin);
1529 * Function called when wlan helper is ready to get some data
1531 * @param cls closure
1532 * @param tc GNUNET_SCHEDULER_TaskContext
1535 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1537 struct Plugin * plugin = cls;
1539 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1540 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1543 struct Session * session;
1544 struct FragmentMessage * fm;
1545 struct ieee80211_frame * ieeewlanheader;
1546 struct Radiotap_Send * radioHeader;
1547 struct GNUNET_MessageHeader * msgheader;
1548 struct FragmentationHeader fragheader;
1549 struct FragmentationHeader * fragheaderptr;
1550 struct Finish_send * finish;
1551 struct AckSendQueue * ack;
1554 const char * copystart;
1558 if (plugin->ack_send_queue_head != NULL)
1560 ack = plugin->ack_send_queue_head;
1561 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1562 plugin->ack_send_queue_tail, ack);
1563 send_ack(plugin, ack);
1568 //test if a "hello-beacon" has to be send
1569 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1571 send_hello_beacon(plugin);
1575 fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1579 session = fm->session;
1580 GNUNET_assert(session != NULL);
1582 // test if message timed out
1583 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1586 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1589 free_fragment_message(plugin, fm);
1590 check_fragment_queue(plugin);
1596 //if (fm->message_size > WLAN_MTU)
1598 size = sizeof(struct FragmentationHeader);
1600 set_next_message_fragment_pos(plugin, fm);
1602 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1605 fragheader.fragment_off_or_num = htons(fm->message_pos);
1606 fragheader.message_id = htonl(fm->message_id_out);
1607 copystart = fm->msg + copyoffset;
1608 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1609 WLAN_MTU - sizeof(struct FragmentationHeader));
1613 GNUNET_ERROR_TYPE_DEBUG,
1614 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1615 fm->message_id_out, fm->message_pos, copysize
1616 + sizeof(struct FragmentationHeader), copyoffset,
1617 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1620 if (copyoffset >= fm->message_size)
1623 GNUNET_ERROR_TYPE_ERROR,
1624 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1625 copyoffset, fm->message_size, WLAN_MTU
1626 - sizeof(struct FragmentationHeader), copysize,
1629 GNUNET_assert(copyoffset < fm->message_size);
1631 fragheader.header.size = htons(copysize
1632 + sizeof(struct FragmentationHeader));
1633 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1636 size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1637 + sizeof(struct GNUNET_MessageHeader);
1638 msgheader = GNUNET_malloc(size);
1639 msgheader->size = htons(size);
1640 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1642 radioHeader = (struct Radiotap_Send*) &msgheader[1];
1643 getRadiotapHeader(plugin, session, radioHeader);
1645 ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1646 getWlanHeader(ieeewlanheader, &(fm->session->addr), plugin, size);
1649 //could be faster if content is just send and not copyed before
1650 //fragmentheader is needed
1651 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1652 memcpy(&ieeewlanheader[1], &fragheader,
1653 sizeof(struct FragmentationHeader));
1654 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1655 memcpy(&fragheaderptr[1], copystart, copysize);
1657 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1659 if (bytes == GNUNET_SYSERR)
1662 GNUNET_ERROR_TYPE_ERROR,
1663 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1664 errno, strerror(errno));
1667 GNUNET_assert(bytes != GNUNET_SYSERR);
1669 //check if this was the last fragment of this message, if true then queue at the end of the list
1670 if (copysize + copyoffset >= fm->message_size)
1672 GNUNET_assert(copysize + copyoffset == fm->message_size);
1674 GNUNET_CONTAINER_heap_update_cost(
1675 plugin->pending_Fragment_Messages, fm->node, MIN(
1676 fm->timeout.abs_value, fm->next_ack.abs_value));
1677 // if fragments have opimized timeouts
1678 //sort_fragment_into_queue(plugin,fm);
1681 #if DEBUG_wlan_retransmission
1683 GNUNET_ERROR_TYPE_DEBUG,
1684 "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1685 fm->message_id_out, fm->message_id_out, fm->message_pos,
1686 fm->message_size, GNUNET_TIME_absolute_get_remaining(
1692 GNUNET_CONTAINER_heap_update_cost(
1693 plugin->pending_Fragment_Messages, fm->node,
1694 GNUNET_TIME_absolute_get().abs_value);
1699 finish = GNUNET_malloc(sizeof( struct Finish_send));
1700 finish->plugin = plugin;
1701 finish->msgheader = (char *) msgheader + bytes;
1702 finish->size = size - bytes;
1703 finish->msgstart = msgheader;
1705 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1707 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1708 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1709 &finish_sending, finish);
1714 GNUNET_free(msgheader);
1715 set_next_send(plugin);
1722 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1723 "do_transmit did nothing, should not happen!\n");
1727 * Another peer has suggested an address for this
1728 * peer and transport plugin. Check that this could be a valid
1729 * address. If so, consider adding it to the list
1732 * @param cls closure
1733 * @param addr pointer to the address
1734 * @param addrlen length of addr
1735 * @return GNUNET_OK if this is a plausible address for this peer
1739 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1741 //struct Plugin *plugin = cls;
1743 /* check if the address is plausible; if so,
1744 add it to our list! */
1746 GNUNET_assert(cls !=NULL);
1747 //FIXME mitm is not checked
1748 //Mac Address has 6 bytes
1751 /* TODO check for bad addresses like multicast, broadcast, etc */
1755 return GNUNET_SYSERR;
1759 * Function that can be used by the transport service to transmit
1760 * a message using the plugin.
1762 * @param cls closure
1763 * @param target who should receive this message
1764 * @param priority how important is the message
1765 * @param msgbuf the message to transmit
1766 * @param msgbuf_size number of bytes in 'msgbuf'
1767 * @param timeout when should we time out
1768 * @param session which session must be used (or NULL for "any")
1769 * @param addr the address to use (can be NULL if the plugin
1770 * is "on its own" (i.e. re-use existing TCP connection))
1771 * @param addrlen length of the address in bytes
1772 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1773 * otherwise the plugin may use other addresses or
1774 * existing connections (if available)
1775 * @param cont continuation to call once the message has
1776 * been transmitted (or if the transport is ready
1777 * for the next transmission call; or if the
1778 * peer disconnected...)
1779 * @param cont_cls closure for cont
1780 * @return number of bytes used (on the physical network, with overheads);
1781 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1782 * and does NOT mean that the message was not transmitted (DV)
1785 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1786 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1787 struct GNUNET_TIME_Relative timeout, struct Session *session,
1788 const void *addr, size_t addrlen, int force_address,
1789 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1791 struct Plugin * plugin = cls;
1792 struct PendingMessage * newmsg;
1793 struct WlanHeader * wlanheader;
1795 //check if msglen > 0
1796 GNUNET_assert(msgbuf_size > 0);
1798 //get session if needed
1799 if (session == NULL)
1801 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1803 session = get_session(plugin, addr);
1807 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1808 _("Wlan Address len %d is wrong\n"), addrlen);
1813 //TODO target "problem" not solved
1814 //if (session->target != NULL){
1815 // GNUNET_assert(session->target == *target);
1817 session->target = *target;
1823 //queue message in session
1824 //test if there is no other message in the "queue"
1825 //FIXME: to many send requests
1826 //GNUNET_assert (session->pending_message == NULL);
1827 if (session->pending_message != NULL)
1829 newmsg = session->pending_message;
1831 GNUNET_ERROR_TYPE_ERROR,
1832 "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages %u\n",
1833 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1834 session->fragment_messages_out_count);
1835 if (session->pending_message2 != NULL)
1838 GNUNET_ERROR_TYPE_ERROR,
1839 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1844 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1845 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1846 wlanheader = (struct WlanHeader *) newmsg->msg;
1847 //copy msg to buffer, not fragmented / segmented yet, but with message header
1848 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1849 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1850 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1851 wlanheader->crc = 0;
1852 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1853 wlanheader->crc = htonl(getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)));
1854 //GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Wlan message Header crc: %u, %u\n",getcrc32((char*) wlanheader, msgbuf_size + sizeof(struct WlanHeader)), wlanheader->crc);
1855 //hexdump(newmsg->msg, msgbuf_size + sizeof(struct WlanHeader));
1857 newmsg->transmit_cont = cont;
1858 newmsg->transmit_cont_cls = cont_cls;
1859 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1861 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1863 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1865 if (session->pending_message == NULL)
1867 session->pending_message = newmsg;
1871 session->pending_message2 = newmsg;
1875 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1876 "New message for %p with size (incl wlan header) %u added\n", session,
1877 newmsg->message_size);
1881 queue_session(plugin, session);
1883 check_fragment_queue(plugin);
1884 //FIXME not the correct size
1890 * Iterate over the fragment messages of the given session.
1892 * @param cls argument to give to iterator
1893 * @param node node to iterate over
1894 * @param element value stored at the node
1895 * @param cost cost associated with the node
1896 * @return GNUNET_YES if we should continue to iterate,
1900 free_fragment_message_from_session(void *cls,
1901 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1902 GNUNET_CONTAINER_HeapCostType cost)
1904 struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
1905 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1907 if (fm->session == pair->session)
1910 free_fragment_message(pair->plugin, fm);
1917 * Search for fragment message with given id and session
1919 * @param cls argument to give to iterator
1920 * @param node node to iterate over
1921 * @param element value stored at the node
1922 * @param cost cost associated with the node
1923 * @return GNUNET_YES if we should continue to iterate,
1927 search_fragment_message_from_session_and_id(void *cls,
1928 struct GNUNET_CONTAINER_HeapNode *node, void *element,
1929 GNUNET_CONTAINER_HeapCostType cost)
1931 struct Session_id_fragment_triple * triple =
1932 (struct Session_id_fragment_triple *) cls;
1933 struct FragmentMessage * fm = (struct FragmentMessage*) element;
1935 if ((fm->session == triple->session) && (fm->message_id_out
1936 == triple->message_id))
1946 * function to get the message in the fragement queue (out) of a session with a specific id
1947 * @param session pointer to the session
1948 * @param message_id id of the message
1949 * @return pointer to the struct FragmentMessage
1951 static struct FragmentMessage *
1952 get_fragment_message_from_session_and_id(struct Plugin * plugin,
1953 struct Session * session, uint32_t message_id)
1955 struct Session_id_fragment_triple triple;
1956 triple.session = session;
1957 triple.message_id = message_id;
1959 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1960 &search_fragment_message_from_session_and_id, &triple);
1965 * function to get the receive message of a session
1966 * @param plugin pointer to the plugin struct
1967 * @param session session this fragment belongs to
1969 static struct Receive_Message_Queue *
1970 get_receive_message_from_session(struct Plugin * plugin,
1971 struct Session * session)
1973 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1974 while (rec_message != NULL)
1976 if (rec_message->session == session)
1980 rec_message = rec_message->next;
1986 * Function to dispose the fragments received for a message and the message
1987 * @param plugin pointer to the plugin struct
1988 * @param rec_message pointer to the struct holding the message which should be freed
1991 free_receive_message(struct Plugin* plugin,
1992 struct Receive_Message_Queue * rx_message)
1994 GNUNET_assert(rx_message !=NULL);
1995 struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1996 struct Receive_Fragment_Queue * rec_queue2;
1998 while (rec_queue != NULL)
2000 rec_queue2 = rec_queue;
2001 rec_queue = rec_queue->next;
2002 GNUNET_free(rec_queue2);
2005 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
2007 GNUNET_assert(plugin->pending_receive_messages > 0);
2008 GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
2010 plugin->pending_receive_messages--;
2011 rx_message->session->fragment_messages_in_count--;
2012 GNUNET_free(rx_message);
2016 * function to get the receive message of a session
2017 * @param plugin pointer to the plugin struct
2018 * @param session session this fragment belongs to
2021 check_receive_message_timeouts(struct Plugin * plugin, struct Session * session)
2023 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2024 while (rec_message != NULL)
2026 if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
2029 free_receive_message(plugin, rec_message);
2031 rec_message = rec_message->next;
2038 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
2040 struct Sessionqueue * pendingsession;
2041 struct Sessionqueue * pendingsession_tmp;
2042 struct PendingMessage * pm;
2043 struct Receive_Message_Queue * receive_queue;
2044 struct Plugin_Session_pair pair;
2047 GNUNET_assert(queue != NULL);
2048 GNUNET_assert(queue->content != NULL);
2051 //is this session pending for send
2052 pendingsession = plugin->pending_Sessions_head;
2053 while (pendingsession != NULL)
2055 pendingsession_tmp = pendingsession->next;
2056 if (pendingsession->content == queue->content)
2058 plugin->pendingsessions--;
2059 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2060 plugin->pending_Sessions_tail,
2062 GNUNET_free(pendingsession);
2064 GNUNET_assert (check == 0);
2067 pendingsession = pendingsession_tmp;
2070 //is something of this session in the fragment queue?
2071 pair.plugin = plugin;
2072 pair.session = queue->content;
2073 GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
2074 &free_fragment_message_from_session, &pair);
2076 //dispose all received fragments
2077 receive_queue = get_receive_message_from_session(plugin, queue->content);
2078 while (receive_queue != NULL)
2080 free_receive_message(plugin, receive_queue);
2081 receive_queue = get_receive_message_from_session(plugin, queue->content);
2084 // remove PendingMessage
2085 pm = queue->content->pending_message;
2088 GNUNET_free_non_null(pm->msg);
2092 // remove PendingMessage
2093 pm = queue->content->pending_message2;
2096 GNUNET_free_non_null(pm->msg);
2100 GNUNET_CONTAINER_DLL_remove(plugin->sessions,
2101 plugin->sessions_tail,
2103 GNUNET_free(queue->content);
2105 plugin->session_count--;
2106 check_fragment_queue(plugin);
2110 * Function that can be used to force the plugin to disconnect
2111 * from the given peer and cancel all previous transmissions
2112 * (and their continuation).
2114 * @param cls closure
2115 * @param target peer from which to disconnect
2118 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
2120 struct Plugin *plugin = cls;
2121 struct Sessionqueue * queue = plugin->sessions;
2123 // just look at all the session for the needed one
2124 while (queue != NULL)
2126 // content is never NULL
2127 GNUNET_assert (queue->content != NULL);
2128 if (memcmp(target, &(queue->content->target),
2129 sizeof(struct GNUNET_PeerIdentity)) == 0)
2131 free_session(plugin, queue);
2135 queue = queue->next;
2140 * Convert the transports address to a nice, human-readable
2143 * @param cls closure
2144 * @param type name of the transport that generated the address
2145 * @param addr one of the addresses of the host, NULL for the last address
2146 * the specific address format depends on the transport
2147 * @param addrlen length of the address
2148 * @param numeric should (IP) addresses be displayed in numeric form?
2149 * @param timeout after how long should we give up?
2150 * @param asc function to call on each string
2151 * @param asc_cls closure for asc
2154 wlan_plugin_address_pretty_printer(void *cls, const char *type,
2155 const void *addr, size_t addrlen, int numeric,
2156 struct GNUNET_TIME_Relative timeout,
2157 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
2160 const unsigned char * input;
2162 //GNUNET_assert(cls !=NULL);
2165 /* invalid address (MAC addresses have 6 bytes) */
2170 input = (const unsigned char*) addr;
2171 GNUNET_snprintf(ret, sizeof(ret),
2172 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2173 input[0], input[1], input[2], input[3], input[4], input[5]);
2178 * Function to test if fragment number already exists in the fragments received
2180 * @param rec_message message this fragment belongs to
2181 * @param fh Fragmentheader of the fragment
2182 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2185 is_double_msg(struct Receive_Message_Queue * rx_msg,
2186 struct FragmentationHeader * fh)
2189 return testBit((char *) &rx_msg->received_fragments, ntohs(
2190 fh->fragment_off_or_num));
2195 * Function to insert a fragment in a queue of a message
2196 * @param session session the fragment belongs to
2197 * @param rec_queue fragment to add
2200 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2201 struct Receive_Fragment_Queue * rx_frag)
2203 GNUNET_assert(rx_message != NULL);
2204 GNUNET_assert(rx_frag != NULL);
2206 struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2207 struct WlanHeader * wlanheader;
2209 //this is the first fragment of the message (fragment id 0)
2210 if (rx_frag->num == 0)
2212 wlanheader = (struct WlanHeader *) rx_frag->msg;
2213 rx_message->rec_size = ntohs(wlanheader->header.size);
2217 while (rx_frag2 != NULL)
2219 if (rx_frag2->num > rx_frag->num)
2221 //next element number is grater than the current num
2222 GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2223 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2226 rx_frag2 = rx_frag2->next;
2229 //no element has a grater number
2230 GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2232 setBit((char *) &rx_message->received_fragments, rx_frag->num);
2236 * handels the data after all fragments are put together
2238 * @param session_light
2239 * @param hdr pointer to the data
2242 wlan_data_message_handler(void *cls, void *client,
2243 const struct GNUNET_MessageHeader *hdr)
2245 struct Plugin * plugin = (struct Plugin*) cls;
2246 struct Session_light * session_light = (struct Session_light *) client;
2247 struct WlanHeader * wlanheader;
2248 struct Session * session;
2249 const char * tempmsg;
2250 const struct GNUNET_MessageHeader * temp_hdr;
2251 struct GNUNET_PeerIdentity tmptarget;
2254 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2259 GNUNET_ERROR_TYPE_DEBUG,
2260 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2264 if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2265 + sizeof(struct GNUNET_MessageHeader))
2267 //packet not big enought
2271 GNUNET_assert(session_light != NULL);
2272 if (session_light->session == NULL)
2274 session_light->session = search_session(plugin, &session_light->addr);
2276 session = session_light->session;
2277 wlanheader = (struct WlanHeader *) hdr;
2279 tempmsg = (char*) &wlanheader[1];
2280 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2281 crc = ntohl(wlanheader->crc);
2282 wlanheader->crc = 0;
2283 if (getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)) != crc)
2285 //wrong crc, dispose message
2286 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2287 "Wlan message Header crc was wrong: %u != %u\n",getcrc32((char *) wlanheader, ntohs(wlanheader->header.size)), crc);
2288 hexdump((void *)hdr, ntohs(hdr->size));
2292 //if not in session list
2293 if (session == NULL)
2297 GNUNET_ERROR_TYPE_DEBUG,
2298 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2299 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2300 sizeof(struct WlanHeader));
2302 //try if it is a hello message
2303 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2304 + sizeof(struct WlanHeader))
2306 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2308 if (GNUNET_HELLO_get_id(
2309 (const struct GNUNET_HELLO_Message *) temp_hdr,
2310 &tmptarget) == GNUNET_OK)
2312 session = create_session(plugin, &session_light->addr);
2313 session_light->session = session;
2314 memcpy(&session->target, &tmptarget,
2315 sizeof(struct GNUNET_PeerIdentity));
2319 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2320 "WLAN client not in session list and hello message not okay\n");
2327 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2328 "WLAN client not in session list and not a hello message\n");
2335 GNUNET_ERROR_TYPE_WARNING,
2336 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2337 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2338 sizeof(struct WlanHeader));
2343 //"receive" the message
2346 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2347 (const char *) temp_hdr,
2348 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2354 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2355 "wlan_data_message_handler got wrong message type\n");
2361 * Function to check if all fragments of a message have been received
2362 * @param plugin the plugin handle
2363 * @param session_light information of the message sender
2364 * @param session session the message belongs to
2365 * @param rec_message pointer to the message that should be checked
2369 check_rx_finished_msg(struct Plugin* plugin,
2370 struct Session_light * session_light, struct Session * session,
2371 struct Receive_Message_Queue * rx_message)
2373 GNUNET_assert(rx_message !=NULL);
2375 struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2376 int packetsize = rx_message->rec_size;
2380 uint64_t bitfield = 0;
2383 //check if first fragment is present
2384 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2388 // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2390 else if (packetsize < sizeof(struct WlanHeader)
2391 + sizeof(struct GNUNET_MessageHeader))
2394 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2396 free_receive_message(plugin, rx_message);
2400 // if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2402 bitfield = ~bitfield;
2403 bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2404 if (rx_message->received_fragments == bitfield)
2407 while (rx_frag != NULL)
2409 sum += rx_frag->size;
2410 rx_frag = rx_frag->next;
2412 //sum should always be smaller or equal of
2413 GNUNET_assert(sum <= packetsize);
2414 if (sum == packetsize)
2418 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2419 "check_rec_finished_msg: A message for %p is complete\n", session);
2424 //copy fragments together
2425 //msg = GNUNET_malloc(packetsize);
2426 rx_frag = rx_message->frag_head;
2428 /*while (rx_frag != NULL)
2430 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2431 memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2432 aktnum += rx_frag->size;
2433 rx_frag = rx_frag->next;
2436 while (rx_frag != NULL)
2438 if (rx_frag->next != NULL)
2440 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2441 session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
2446 //if it is the last fragment just kill all leftover
2447 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2448 session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
2451 rx_frag = rx_frag->next;
2453 free_receive_message(plugin, rx_message);
2454 //call wlan_process_helper to process the message
2455 //wlan_data_message_handler(plugin, session_light,
2456 // (struct GNUNET_MessageHeader*) msg);
2457 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2467 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2470 GNUNET_assert(client != NULL);
2471 GNUNET_assert(cls != NULL);
2472 struct Session * session = (struct Session *) client;
2473 struct Plugin * plugin = (struct Plugin *) cls;
2475 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2476 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2477 distance[0].value = htonl(1);
2478 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2479 distance[1].value = htonl(0);
2482 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2483 "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2484 wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
2488 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2489 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2490 (const char*) &session->addr, sizeof(session->addr));
2494 * function to add an ack to send it for a received fragment
2495 * @param plugin pointer to the global plugin structure
2496 * @param session pointer to the session this ack belongs to
2497 * @param bitfield bitfield to send
2498 * @param fh pointer to the fragmentation header which we would like to acknolage
2502 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2503 uint64_t bitfield, struct FragmentationHeader * fh)
2505 struct AckSendQueue * ack;
2507 GNUNET_assert(plugin != NULL);
2508 GNUNET_assert(session != NULL);
2509 GNUNET_assert(fh != NULL);
2511 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2512 ack->fragments_field = bitfield;
2513 ack->message_id = ntohl(fh->message_id);
2514 ack->session = session;
2516 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2517 plugin->ack_send_queue_tail, ack);
2522 * function to get the receive message from the message id and the session
2523 * @param plugin pointer to the plugin struct
2524 * @param session session this fragment belongs to
2525 * @param message_id id of the message
2528 struct Receive_Message_Queue *
2529 get_receive_message(struct Plugin * plugin, struct Session * session,
2530 uint32_t message_id)
2532 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2533 while (rec_message != NULL)
2535 if ((rec_message->message_id_in == message_id) && (rec_message->session
2540 rec_message = rec_message->next;
2546 * function to insert a received fragment into the right fragment queue of the right message
2547 * @param plugin pointer to the plugin struct
2548 * @param session_light pointer to the session_light struct of this message
2549 * @param session session this fragment belongs to
2550 * @param fh pointer to the header of the fragment
2551 * @return new fragment bitfield for the message
2555 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2556 struct Session_light * session_light, struct Session * session,
2557 struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2559 struct Receive_Fragment_Queue * rx_frag = NULL;
2560 struct Receive_Message_Queue * rx_message;
2561 const char * tempmsg = (char*) &fh[1];
2562 uint64_t retval = 0;
2564 //TODO fragments do not timeout
2565 //check if message_id is right or it is a new msg
2566 GNUNET_assert(fh != NULL);
2568 rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2570 if (rx_message == NULL)
2572 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2574 check_receive_message_timeouts(plugin, session);
2577 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2580 //new message incoming
2581 rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2582 rx_message->message_id_in = ntohl(fh->message_id);
2583 rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2584 rx_message->session = session;
2585 rx_message->received_fragments = 0;
2587 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2589 session->fragment_messages_in_count++;
2590 plugin->pending_receive_messages++;
2594 GNUNET_ERROR_TYPE_DEBUG,
2595 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2596 rx_message->message_id_in, session->fragment_messages_in_count,
2597 plugin->pending_receive_messages);
2604 GNUNET_ERROR_TYPE_INFO,
2605 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
2606 get_receive_message_from_session(plugin, session)->message_id_in);
2607 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2613 rx_message->timeout = GNUNET_TIME_absolute_add(
2614 GNUNET_TIME_absolute_get(),
2615 MESSAGE_IN_TIMEOUT);
2617 if (is_double_msg(rx_message, fh) != GNUNET_YES)
2621 rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2622 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2623 rx_frag->size = ntohs(fh->header.size)
2624 - sizeof(struct FragmentationHeader);
2625 rx_frag->num = ntohs(fh->fragment_off_or_num);
2626 rx_frag->msg = (char*) &(rx_frag[1]);
2627 //copy msg to buffer
2628 memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2629 memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2630 insert_fragment_in_queue(rx_message, rx_frag);
2632 retval = rx_message->received_fragments;
2636 GNUNET_ERROR_TYPE_DEBUG,
2637 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2638 rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2639 rx_message->received_fragments, session);
2642 check_rx_finished_msg(plugin, session_light, session, rx_message);
2646 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2647 retval = rx_message->received_fragments;
2655 * Function used for to process the data received from the wlan interface
2657 * @param cls the plugin handle
2658 * @param session_light FIXME: document
2659 * @param hdr hdr of the GNUNET_MessageHeader
2662 wlan_data_helper(void *cls, struct Session_light * session_light,
2663 const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2665 struct Plugin *plugin = cls;
2666 struct Session * session;
2668 struct FragmentationHeader * fh;
2669 struct FragmentationAckHeader * fah;
2670 struct FragmentMessage * fm;
2672 const char * tempmsg;
2674 uint64_t fragment_bitfield = 0;
2677 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2680 //TODO better DOS protection, error handling
2681 //TODO test first than create session
2682 GNUNET_assert(session_light != NULL);
2686 GNUNET_ERROR_TYPE_DEBUG,
2687 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2688 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2689 session_light->addr.mac, 6));
2692 if (session_light->session == NULL)
2694 session_light->session = get_session(plugin, &session_light->addr);
2696 GNUNET_assert(GNUNET_HELLO_get_id(
2697 (const struct GNUNET_HELLO_Message *) &hdr[1],
2698 &(session_light->session->target) ) != GNUNET_SYSERR);
2704 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2707 GNUNET_assert(session_light != NULL);
2708 if (session_light->session == NULL)
2710 session_light->session = search_session(plugin, &session_light->addr);
2712 session = session_light->session;
2714 fh = (struct FragmentationHeader *) hdr;
2715 tempmsg = (char*) &fh[1];
2719 GNUNET_ERROR_TYPE_DEBUG,
2720 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2721 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2722 hdr->size), wlan_plugin_address_to_string(NULL,
2723 session_light->addr.mac, 6));
2726 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2728 //wrong crc, dispose message
2729 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2733 //if in the session list
2734 if (session != NULL)
2736 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2737 session_light, session, fh, rxinfo);
2743 GNUNET_ERROR_TYPE_INFO,
2744 "WLAN client not in session list, fragment num %u, message id %u\n",
2745 ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2747 GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
2748 tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
2749 GNUNET_YES, GNUNET_NO);
2750 //wlan_data_message_handler(plugin, session_light,
2751 // (struct GNUNET_MessageHeader *) tempmsg);
2752 session = session_light->session;
2753 //test if a session was created
2754 if (session == NULL)
2758 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2761 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2762 set_next_send(plugin);
2768 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2773 GNUNET_ERROR_TYPE_DEBUG,
2774 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2775 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2776 session_light->addr.mac, 6));
2779 GNUNET_assert(session_light != NULL);
2780 if (session_light->session == NULL)
2782 session_light->session = search_session(plugin, &session_light->addr);
2783 GNUNET_assert(session_light->session != NULL);
2785 session = session_light->session;
2786 fah = (struct FragmentationAckHeader *) hdr;
2787 fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
2793 fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
2794 fah->fragment_field);
2795 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
2797 #if DEBUG_wlan_retransmission
2798 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
2799 fm->message_id_out, fm->ack_bitfield);
2801 check_finished_fragment(plugin, fm);
2802 set_next_send(plugin);
2807 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2808 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2818 GNUNET_ERROR_TYPE_INFO,
2819 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2820 ntohs(hdr->type), ntohs(hdr->size));
2826 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2827 "Helper finished\n");
2834 macprinter(const u_int8_t * mac)
2836 static char macstr[20];
2838 GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2839 mac[2], mac[3], mac[4], mac[5]);
2844 * Function used for to process the data from the suid process
2846 * @param cls the plugin handle
2847 * @param client client that send the data (not used)
2848 * @param hdr header of the GNUNET_MessageHeader
2851 wlan_process_helper(void *cls, void *client,
2852 const struct GNUNET_MessageHeader *hdr)
2854 struct Plugin *plugin = cls;
2855 struct ieee80211_frame * wlanIeeeHeader = NULL;
2856 struct Session_light * session_light = NULL;
2857 struct Radiotap_rx * rxinfo;
2858 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2863 switch (ntohs(hdr->type))
2865 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2868 GNUNET_ERROR_TYPE_DEBUG,
2869 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2873 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2874 if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2875 + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2878 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2879 "Size of packet is too small; size: %u min size: %u\n", ntohs(
2880 hdr->size), sizeof(struct ieee80211_frame)
2881 + sizeof(struct GNUNET_MessageHeader));
2884 /* FIXME: restart SUID process */
2887 rxinfo = (struct Radiotap_rx *) &hdr[1];
2888 wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2890 //process only if it is an broadcast or for this computer both with the gnunet bssid
2893 if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
2894 sizeof(struct MacAddress)) == 0)
2896 //check for broadcast or mac
2897 if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2898 sizeof(struct MacAddress) == 0) || memcmp(
2899 &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2900 sizeof(struct MacAddress)) == 0)
2903 // process the inner data
2906 datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2907 - sizeof(struct GNUNET_MessageHeader)
2908 - sizeof(struct Radiotap_rx);
2910 session_light = GNUNET_malloc(sizeof(struct Session_light));
2911 memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2912 sizeof(struct MacAddress));
2913 //session_light->session = search_session(plugin,session_light->addr);
2916 while (pos < datasize)
2918 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2921 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2922 pos += ntohs(temp_hdr->size);
2927 GNUNET_free(session_light);
2932 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2933 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2934 wlanIeeeHeader->i_addr1));
2941 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2942 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2943 wlanIeeeHeader->i_addr2));
2947 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2948 //TODO more control messages
2949 //TODO use struct wlan_helper_control
2950 if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2953 /* FIXME: restart SUID process */
2956 memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2958 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2959 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2960 wlan_plugin_address_to_string(cls, &plugin->mac_address,
2961 sizeof(struct MacAddress)));
2963 plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2964 sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2973 * We have been notified that wlan-helper has written something to stdout.
2974 * Handle the output, then reschedule this function to be called again once
2975 * more is available.
2977 * @param cls the plugin handle
2978 * @param tc the scheduling context
2981 wlan_plugin_helper_read(void *cls,
2982 const struct GNUNET_SCHEDULER_TaskContext *tc)
2984 struct Plugin *plugin = cls;
2985 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2987 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2990 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2993 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2998 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2999 _("Finished reading from wlan-helper stdout with code: %d\n"),
3004 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
3005 GNUNET_NO, GNUNET_NO);
3007 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3008 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3009 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3010 &wlan_plugin_helper_read, plugin);
3014 * Start the gnunet-wlan-helper process.
3016 * @param plugin the transport plugin
3017 * @param testmode should we use the dummy driver for testing?
3018 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
3021 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
3023 const char * filenamehw = "gnunet-transport-wlan-helper";
3024 const char * filenameloopback = "gnunet-transport-wlan-helper-dummy";
3025 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
3026 if (plugin->server_stdout == NULL)
3027 return GNUNET_SYSERR;
3029 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
3030 if (plugin->server_stdin == NULL)
3031 return GNUNET_SYSERR;
3034 /* Start the server process */
3040 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3041 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filenamehw,
3042 plugin->interface, testmode);
3045 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3046 plugin->server_stdout, filenamehw, filenamehw, plugin->interface, NULL);
3048 else if (testmode == 1)
3052 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3053 "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n", filenameloopback,
3054 plugin->interface, testmode);
3057 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3058 plugin->server_stdout, filenameloopback, filenameloopback, "1", NULL);
3060 else if (testmode == 2)
3063 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3064 "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n", filenameloopback,
3065 plugin->interface, testmode);
3067 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
3068 plugin->server_stdout, filenameloopback, filenameloopback, "2", NULL);
3070 if (plugin->server_proc == NULL)
3073 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3074 "Failed to start gnunet-wlan-helper process\n");
3076 return GNUNET_SYSERR;
3079 /* Close the write end of the read pipe */
3080 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
3082 /* Close the read end of the write pipe */
3083 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
3085 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
3086 GNUNET_DISK_PIPE_END_READ);
3087 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
3088 GNUNET_DISK_PIPE_END_WRITE);
3090 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
3093 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3094 "Adding server_read_task for the wlan-helper\n");
3097 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
3098 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
3099 &wlan_plugin_helper_read, plugin);
3105 * Exit point from the plugin.
3106 * @param cls pointer to the api struct
3111 libgnunet_plugin_transport_wlan_done(void *cls)
3113 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3114 struct Plugin *plugin = api->cls;
3115 struct Sessionqueue * queue = plugin->sessions;
3116 struct Sessionqueue * queue_next;
3117 struct FragmentMessage * fm;
3120 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3121 "libgnunet_plugin_transport_wlan_done started\n");
3125 GNUNET_DISK_pipe_close(plugin->server_stdout);
3126 GNUNET_DISK_pipe_close(plugin->server_stdin);
3127 GNUNET_OS_process_kill(plugin->server_proc,9);
3128 GNUNET_OS_process_close(plugin->server_proc);
3131 GNUNET_assert (cls !=NULL);
3133 while (queue != NULL)
3135 queue_next = queue->next;
3136 free_session(plugin, queue);
3140 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
3142 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
3143 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3145 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
3147 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
3148 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3150 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
3152 GNUNET_SCHEDULER_cancel(plugin->server_read_task);
3153 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3156 if (plugin->suid_tokenizer != NULL)
3157 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
3159 if (plugin->data_tokenizer != NULL)
3160 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3162 if (plugin->fragment_tokenizer != NULL)
3163 GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
3165 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3166 plugin->pending_Fragment_Messages);
3170 free_fragment_message(plugin, fm);
3171 fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3172 plugin->pending_Fragment_Messages);
3175 GNUNET_free_non_null(plugin->interface);
3176 GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
3177 GNUNET_free (plugin);
3183 * Entry point for the plugin.
3185 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3186 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3189 libgnunet_plugin_transport_wlan_init(void *cls)
3191 //struct GNUNET_SERVICE_Context *service;
3192 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3193 struct GNUNET_TRANSPORT_PluginFunctions *api;
3194 struct Plugin *plugin;
3195 static unsigned long long testmode = 0;
3197 GNUNET_assert(cls !=NULL);
3199 plugin = GNUNET_malloc (sizeof (struct Plugin));
3201 plugin->pendingsessions = 0;
3202 plugin->session_count = 0;
3203 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3204 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3205 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3206 plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
3207 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3209 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3212 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3213 plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
3214 &wlan_data_message_handler, plugin);
3216 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3217 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3219 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3221 api->send = &wlan_plugin_send;
3222 api->disconnect = &wlan_plugin_disconnect;
3223 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3224 api->check_address = &wlan_plugin_address_suggested;
3225 api->address_to_string = &wlan_plugin_address_to_string;
3228 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3230 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3231 "transport-wlan", "TESTMODE", &testmode))
3232 testmode = 0; //default value
3235 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3237 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3238 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3240 libgnunet_plugin_transport_wlan_done(api);
3246 set_next_beacon_time(plugin);
3248 wlan_transport_start_wlan_helper(plugin, testmode);
3251 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3257 /* end of plugin_transport_wlan.c */