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"
38 #define PROTOCOL_PREFIX "wlan"
41 * Max size of packet from helper
46 * Time until retransmission of a fragment in ms
48 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
50 #define FRAGMENT_QUEUE_SIZE 10
51 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
53 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
55 #define MESSAGES_IN_QUEUE_SIZE 10
56 #define MESSAGES_IN_QUEUE_PER_SESSION 1
58 #define HALLO_BEACON_SCALING_FACTOR 900
60 #define DEBUG_wlan GNUNET_YES
62 #define MESSAGE_LENGHT_UNKNOWN -1
63 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
66 * After how long do we expire an address that we
67 * learned from another peer if it is not reconfirmed
70 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
73 * Initial handshake message for a session.
78 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
80 struct GNUNET_MessageHeader header;
83 * Identit*mac_y of the node connecting (TCP client)
85 struct GNUNET_PeerIdentity clientIdentity;
90 * Encapsulation of all of the state of the plugin.
97 struct GNUNET_TRANSPORT_PluginEnvironment *env;
100 * List of open sessions. head
102 struct Sessionqueue *sessions;
105 * List of open sessions. tail
107 struct Sessionqueue *sessions_tail;
116 * encapsulation of data from the local wlan helper program
119 struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
122 * encapsulation of packets received
125 struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
128 * stdout pipe handle for the gnunet-wlan-helper process
130 struct GNUNET_DISK_PipeHandle *server_stdout;
133 * stdout file handle for the gnunet-wlan-helper process
135 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
138 * stdin pipe handle for the gnunet-wlan-helper process
140 struct GNUNET_DISK_PipeHandle *server_stdin;
143 * stdin file handle for the gnunet-wlan-helper process
145 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
148 * ID of the gnunet-wlan-server std read task
150 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
153 * ID of the gnunet-wlan-server std read task
155 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
158 * ID of the delay task for writing
160 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
163 * The process id of the wlan process
165 struct GNUNET_OS_Process *server_proc;
168 * The interface of the wlan card given to us by the user.
173 * The mac_address of the wlan card given to us by the helper.
175 struct MacAddress mac_address;
178 * Sessions currently pending for transmission
179 * to this peer, if any.
181 struct Sessionqueue * pending_Sessions;
184 * Sessions currently pending for transmission
185 * to this peer (tail), if any.
187 struct Sessionqueue * pending_Sessions_tail;
190 * number of pending sessions
192 unsigned int pendingsessions;
195 * Messages in the fragmentation queue, head
198 struct FragmentMessage * pending_Fragment_Messages_head;
201 * Messages in the fragmentation queue, tail
204 struct FragmentMessage * pending_Fragment_Messages_tail;
207 * number of pending fragment message
210 unsigned int pending_fragment_messages;
213 * Messages in the in Queue, head
216 struct Receive_Message_Queue * receive_messages_head;
219 * Messages in the in Queue, tail
222 struct Receive_Message_Queue * receive_messages_teil;
225 * number of messages in the in queue
228 unsigned int pending_receive_messages;
231 * time of the next "hello-beacon"
234 struct GNUNET_TIME_Absolute beacon_time;
237 * queue to send acks for received fragments (head)
240 struct AckSendQueue * ack_send_queue_head;
243 * queue to send acks for received fragments (tail)
246 struct AckSendQueue * ack_send_queue_tail;
251 * Struct to store data if file write did not accept the whole packet
255 struct Plugin * plugin;
257 struct GNUNET_MessageHeader * msgstart;
262 * Queue of sessions, for the general session queue and the pending session queue
267 struct Sessionqueue * next;
268 struct Sessionqueue * prev;
269 struct Session * content;
273 * Queue for the fragments received
276 struct Receive_Fragment_Queue
278 struct Receive_Fragment_Queue * next;
279 struct Receive_Fragment_Queue * prev;
286 * Queue for the fragments received
289 struct Receive_Message_Queue
291 struct Receive_Message_Queue * next;
293 struct Receive_Message_Queue * prev;
296 * current number for message incoming, to distinguish between the messages
298 uint32_t message_id_in;
301 * size of the message received,
302 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
303 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
309 * Sorted queue with the fragments received; head
312 struct Receive_Fragment_Queue * frag_head;
315 * Sorted queue with the fragments received; tail
318 struct Receive_Fragment_Queue * frag_tail;
321 * Session this fragment belongs to
324 struct Session * session;
327 * Timeout value for the pending message.
329 struct GNUNET_TIME_Absolute timeout;
332 * Bitfield of received fragments
335 uint64_t received_fragments;
339 * Information kept for each message that is yet to
342 struct PendingMessage
346 * The pending message
351 * Size of the message
356 * Continuation function to call once the message
357 * has been sent. Can be NULL if there is no
358 * continuation to call.
360 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
363 * Cls for transmit_cont
365 void * transmit_cont_cls;
368 * Timeout value for the pending message.
370 struct GNUNET_TIME_Absolute timeout;
375 * Queue for acks to send for fragments recived
381 struct AckSendQueue * next;
382 struct AckSendQueue * prev;
384 struct Session * session;
386 * ID of message, to distinguish between the messages, picked randomly.
391 * Bit field for received fragments
393 uint64_t fragments_field;
398 * Session infos gathered from a messages
404 * the session this message belongs to
406 struct Session * session;
414 * Session handle for connections.
422 struct SessionHeader header;
425 * Pointer to the global plugin struct.
427 struct Plugin *plugin;
430 * Message currently pending for transmission
431 * to this peer, if any.
433 struct PendingMessage *pending_message;
436 * Message currently pending for transmission
437 * to this peer, if any.
439 struct PendingMessage *pending_message2;
442 * To whom are we talking to (set to our identity
443 * if we are still waiting for the welcome message)
445 struct GNUNET_PeerIdentity target;
453 * Address of the other peer (either based on our 'connect'
454 * call or on our 'accept' call).
459 * Last activity on this connection. Used to select preferred
462 struct GNUNET_TIME_Absolute last_activity;
465 * count of messages in the fragment out queue for this session
468 int fragment_messages_out_count;
471 * count of messages in the fragment in queue for this session
474 int fragment_messages_in_count;
479 * Struct for Messages in the fragment queue
482 struct FragmentMessage
485 * Session this message belongs to
488 struct Session *session;
491 * This is a doubly-linked list.
493 struct FragmentMessage *next;
496 * This is a doubly-linked list.
498 struct FragmentMessage *prev;
501 * The pending message
506 * Timeout value for the pending message.
508 struct GNUNET_TIME_Absolute timeout;
511 * Timeout value for the pending fragments.
512 * Stores the time when the next msg fragment ack has to be received
514 struct GNUNET_TIME_Absolute next_ack;
517 * bitfield with all acks received for this message
519 uint64_t ack_bitfield;
522 * Size of the message
527 * pos / next fragment number in the message, for fragmentation/segmentation,
528 * some acks can be missing but there is still time
530 uint32_t message_pos;
533 * current number for message outgoing, to distinguish between the messages
535 uint32_t message_id_out;
539 * Header for messages which need fragmentation
544 struct GNUNET_MessageHeader header;
547 * checksum/error correction
549 uint32_t crc GNUNET_PACKED;
552 * To whom are we talking to (set to our identity
553 * if we are still waiting for the welcome message)
555 struct GNUNET_PeerIdentity target;
557 // followed by payload
562 * Header for messages which need fragmentation
564 struct FragmentationHeader
567 struct GNUNET_MessageHeader header;
570 * ID of message, to distinguish between the messages, picked randomly.
572 uint32_t message_id GNUNET_PACKED;
575 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
577 uint16_t fragment_off_or_num GNUNET_PACKED;
580 * CRC of fragment (for error checking)
582 uint16_t message_crc GNUNET_PACKED;
584 // followed by payload
589 * Header for messages which need fragmentation
591 struct FragmentationAckHeader
594 struct GNUNET_MessageHeader header;
597 * ID of message, to distinguish between the messages, picked randomly.
599 uint32_t message_id GNUNET_PACKED;
602 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
604 uint64_t fragment_field GNUNET_PACKED;
609 getRadiotapHeader(struct RadiotapHeader * Header);
612 getWlanHeader(struct IeeeHeader * Header, const char * to_mac_addr,
613 struct Plugin * plugin);
616 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
619 getcrc16(const char *msgbuf, size_t msgbuf_size);
622 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
625 check_fragment_queue(struct Plugin * plugin);
628 getcrc32(const char *msgbuf, size_t msgbuf_size);
631 free_receive_message(struct Plugin* plugin,
632 struct Receive_Message_Queue * rec_message);
634 struct Receive_Message_Queue *
635 get_receive_message_from_session(struct Plugin * plugin,
636 struct Session * session);
639 wlan_data_helper(void *cls, struct Session_light * session_light,
640 const struct GNUNET_MessageHeader * hdr);
643 wlan_process_helper(void *cls, void *client,
644 const struct GNUNET_MessageHeader *hdr);
647 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
650 wlan_data_massage_handler(struct Plugin * plugin,
651 struct Session_light * session_light,
652 const struct GNUNET_MessageHeader * hdr);
655 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen);
657 struct Receive_Message_Queue *
658 get_receive_message(struct Plugin * plugin, struct Session * session,
659 uint32_t message_id);
662 htonll(uint64_t input)
668 ntohll(uint64_t input)
674 * Sets a bit active in the bitArray. Increment bit-specific
675 * usage counter on disk only if below 4bit max (==15).
677 * @param bitArray memory area to set the bit in
678 * @param bitIdx which bit to set
681 setBit(char *bitArray, unsigned int bitIdx)
684 unsigned int targetBit;
686 arraySlot = bitIdx / 8;
687 targetBit = (1L << (bitIdx % 8));
688 bitArray[arraySlot] |= targetBit;
692 * Clears a bit from bitArray. Bit is cleared from the array
693 * only if the respective usage counter on the disk hits/is zero.
695 * @param bitArray memory area to set the bit in
696 * @param bitIdx which bit to unset
699 clearBit(char *bitArray, unsigned int bitIdx)
702 unsigned int targetBit;
705 targetBit = (1L << (bitIdx % 8));
706 bitArray[slot] = bitArray[slot] & (~targetBit);
710 * Checks if a bit is active in the bitArray
712 * @param bitArray memory area to set the bit in
713 * @param bitIdx which bit to test
714 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
717 testBit(char *bitArray, unsigned int bitIdx)
720 unsigned int targetBit;
723 targetBit = (1L << (bitIdx % 8));
724 if (bitArray[slot] & targetBit)
731 * Sets a bit active in the bitArray.
733 * @param bitArray memory area to set the bit in
734 * @param bitIdx which bit to set
737 setBit (uint64_t bitArray, unsigned int bitIdx)
741 targetBit = (1ULL << bitIdx);
742 return bitArray | targetBit;
746 * Clears a bit from bitArray.
748 * @param bitArray memory area to set the bit in
749 * @param bitIdx which bit to unset
752 clearBit (uint64_t bitArray, unsigned int bitIdx)
756 targetBit = (1ULL << bitIdx);
757 return bitArray & (~targetBit);
761 * Checks if a bit is active in the bitArray
763 * @param bitArray memory area to set the bit in
764 * @param bitIdx which bit to test
765 * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
768 testBit (uint64_t bitArray, unsigned int bitIdx)
773 targetBit = (1ULL << bitIdx);
774 if (bitArray & targetBit)
781 * get the next message number, at the moment just a random one
782 * @return returns the next valid message-number for sending packets
785 get_next_message_id()
787 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
791 * start next message number generator
792 * (not necessary at the moment)
795 start_next_message_id()
797 //GNUNET_CRYPTO_random_init;
801 * search for a session with the addr
803 * @param plugin pointer to the plugin struct
804 * @param addr pointer to the mac address of the peer
805 * @return returns the session
808 static struct Session *
809 search_session(struct Plugin *plugin, const uint8_t * addr)
811 struct Sessionqueue * queue = plugin->sessions;
812 struct Sessionqueue * lastitem = NULL;
814 //just look at all the session for the needed one
815 while (queue != NULL)
817 // content is never NULL
818 GNUNET_assert (queue->content != NULL);
819 char * addr2 = queue->content->addr;
820 if (memcmp(addr, addr2, 6) == 0)
823 return queue->content;
833 * create a new session
835 * @param plugin pointer to the plugin struct
836 * @param addr pointer to the mac address of the peer
837 * @return returns the session
840 static struct Session *
841 create_session(struct Plugin *plugin, const uint8_t * addr)
843 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
845 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
847 queue->content = GNUNET_malloc (sizeof (struct Session));
848 queue->content->plugin = plugin;
849 memcpy(queue->content->addr, addr, 6);
850 queue->content->fragment_messages_out_count = 0;
851 queue->content->fragment_messages_in_count = 0;
853 plugin->session_count++;
856 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
857 queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
860 return queue->content;
864 * get Session from address, create if no session exists
866 * @param plugin pointer to the plugin struct
867 * @param addr pointer to the mac address of the peer
868 * @return returns the session
870 //TODO add other possibilities to find the right session (are there other?)
871 static struct Session *
872 get_Session(struct Plugin *plugin, const uint8_t * addr)
874 struct Session * session = search_session(plugin, addr);
880 return create_session(plugin, addr);
882 /* -- not needed, layer above already has it--
883 //queue welcome message for new sessions, not realy needed
884 //struct WelcomeMessage welcome;
885 struct PendingMessage *pm;
886 pm = GNUNET_malloc (sizeof (struct PendingMessage));
887 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
888 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
889 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
890 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
891 //welcome.clientIdentity = *plugin->env->my_identity;
892 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
893 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
894 queue->content->pending_message = pm;
895 plugin->pendingsessions ++;
896 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
898 check_fragment_queue(plugin);
903 * Queue the session to send data
907 queue_Session(struct Plugin *plugin, struct Session * session)
909 struct Sessionqueue * queue = plugin->pending_Sessions;
910 struct Sessionqueue * lastitem = NULL;
912 while (queue != NULL)
914 // content is never NULL
915 GNUNET_assert (queue->content != NULL);
916 // is session already in queue?
917 if (session == queue->content)
926 // Session is not in the queue
928 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
929 queue->content = session;
932 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
933 plugin->pending_Sessions_tail,
934 plugin->pending_Sessions_tail, queue);
935 plugin->pendingsessions++;
941 * Function to schedule the write task, executed after a delay
944 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
946 struct Plugin * plugin = cls;
947 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
949 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
952 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
953 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
955 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
956 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
957 &do_transmit, plugin);
963 * Function to calculate the time of the next periodic "hello-beacon"
966 set_next_beacon_time(struct Plugin * const plugin)
968 //under 10 known peers: once a second
969 if (plugin->session_count < 10)
971 plugin->beacon_time = GNUNET_TIME_absolute_add(
972 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
973 GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
975 //under 30 known peers: every 10 seconds
976 else if (plugin->session_count < 30)
978 plugin->beacon_time = GNUNET_TIME_absolute_add(
979 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
980 GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
982 //over 30 known peers: once a minute
985 plugin->beacon_time = GNUNET_TIME_absolute_add(
986 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
987 GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
992 struct GNUNET_TIME_Relative
993 get_next_frag_timeout(struct FragmentMessage * fm)
995 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
996 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
1001 * Function to get the timeout value for acks for this session
1004 struct GNUNET_TIME_Relative
1005 get_ack_timeout(struct FragmentMessage * fm)
1007 return FRAGMENT_TIMEOUT;
1011 * Function to set the timer for the next timeout of the fragment queue
1012 * @param plugin the handle to the plugin struct
1015 check_next_fragment_timeout(struct Plugin * const plugin)
1017 struct FragmentMessage * fm;
1018 struct GNUNET_TIME_Relative next_send;
1020 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
1023 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1025 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
1026 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1028 fm = plugin->pending_Fragment_Messages_head;
1030 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
1032 //check if some acks are in the queue
1033 if (plugin->ack_send_queue_head != NULL)
1035 next_send = GNUNET_TIME_relative_get_zero();
1037 //check if there are some fragments in the queue
1038 else if (fm != NULL)
1041 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
1043 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
1044 &delay_fragment_task, plugin);
1049 * Function to get the next queued Session, removes the session from the queue
1052 static struct Session *
1053 get_next_queue_Session(struct Plugin * plugin)
1055 struct Session * session;
1056 struct Sessionqueue * sessionqueue;
1057 struct Sessionqueue * sessionqueue_alt;
1058 struct PendingMessage * pm;
1059 sessionqueue = plugin->pending_Sessions;
1060 while (sessionqueue != NULL)
1062 session = sessionqueue->content;
1064 pm = session->pending_message;
1067 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1068 "pending message is empty, should not happen. session %p\n", session);
1071 GNUNET_assert(pm != NULL);
1073 //check for message timeout
1074 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
1076 //check if session has no message in the fragment queue
1077 if (session->fragment_messages_out_count
1078 < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
1080 plugin->pendingsessions--;
1081 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1082 plugin->pending_Sessions_tail, sessionqueue);
1083 GNUNET_free(sessionqueue);
1089 sessionqueue = sessionqueue->next;
1095 session->pending_message = session->pending_message2;
1096 session->pending_message2 = NULL;
1098 //call the cont func that it did not work
1099 if (pm->transmit_cont != NULL)
1100 pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
1102 GNUNET_free(pm->msg);
1105 if (session->pending_message == NULL)
1107 sessionqueue_alt = sessionqueue;
1108 sessionqueue = sessionqueue->next;
1109 plugin->pendingsessions--;
1110 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1111 plugin->pending_Sessions_tail, sessionqueue_alt);
1113 GNUNET_free(sessionqueue_alt);
1123 * Function to sort the message into the message fragment queue
1124 * @param plugin the plugin struct
1125 * @param fm message to sort into the queue
1128 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
1130 struct FragmentMessage * fm2;
1131 //sort into the list at the right position
1133 fm2 = plugin->pending_Fragment_Messages_head;
1137 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
1148 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
1149 plugin->pending_Fragment_Messages_tail,fm2,fm);
1153 * frees the space of a message in the fragment queue (send queue)
1154 * @param plugin the plugin struct
1155 * @param fm message to free
1158 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
1162 (fm->session->fragment_messages_out_count)--;
1163 GNUNET_free_non_null(fm->msg);
1164 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1165 plugin->pending_Fragment_Messages_tail, fm);
1167 plugin->pending_fragment_messages--;
1170 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1171 "free pending fragment messages, pending messages remaining %u\n",
1172 plugin->pending_fragment_messages);
1178 * Function to check if there is some space in the fragment queue
1179 * inserts a message if space is available
1180 * @param plugin the plugin struct
1184 check_fragment_queue(struct Plugin * plugin)
1186 struct Session * session;
1187 struct FragmentMessage * fm;
1188 struct GNUNET_PeerIdentity pid;
1190 struct PendingMessage * pm;
1192 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
1194 session = get_next_queue_Session(plugin);
1195 if (session != NULL)
1197 pm = session->pending_message;
1198 session->pending_message = NULL;
1199 session->fragment_messages_out_count++;
1200 GNUNET_assert(pm != NULL);
1202 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1203 fm->message_size = pm->message_size;
1205 fm->session = session;
1206 fm->timeout.abs_value = pm->timeout.abs_value;
1207 fm->message_pos = 0;
1208 fm->next_ack = GNUNET_TIME_absolute_get();
1209 fm->message_id_out = get_next_message_id();
1210 fm->ack_bitfield = 0;
1212 sort_fragment_into_queue(plugin, fm);
1213 plugin->pending_fragment_messages++;
1215 if (pm->transmit_cont != NULL)
1217 pid = session->target;
1218 pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1220 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1221 "called pm->transmit_cont for %p\n", session);
1227 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1228 "no pm->transmit_cont for %p\n", session);
1233 if (session->pending_message2 != NULL){
1234 session->pending_message = session->pending_message2;
1235 session->pending_message2 = NULL;
1237 queue_Session(plugin, session);
1240 //check if timeout changed
1241 check_next_fragment_timeout(plugin);
1247 * Funktion to check if all fragments where send and the acks received
1248 * frees the space if finished
1249 * @param plugin the plugin struct
1250 * @param fm the message to check
1253 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1255 //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1256 unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1257 - sizeof(struct FragmentationHeader)));
1258 uint64_t tmpfield = 0xFFFFFFFFFFFFFFFF;
1259 tmpfield = tmpfield >> maxack;
1263 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1264 "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1265 fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1268 if (fm->ack_bitfield == tmpfield)
1271 free_fragment_message(plugin, fm);
1274 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1275 "Finished sending and got all acks for a fragmented message\n");
1278 check_next_fragment_timeout(plugin);
1279 check_fragment_queue(plugin);
1285 * Function to set the next fragment number
1286 * @param fm use this FragmentMessage
1290 set_next_message_fragment_pos(struct FragmentMessage * fm)
1293 //check if retransmit is needed
1294 if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1297 // be positive and try again later :-D
1298 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1299 // find first missing fragment
1301 fm->message_pos = 0;
1304 //test if ack 0 (or X) was already received
1305 while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1313 send_hello_beacon(struct Plugin * plugin)
1317 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1322 struct GNUNET_MessageHeader * msgheader = NULL;
1323 struct IeeeHeader * ieeewlanheader = NULL;
1324 struct RadiotapHeader * radioHeader = NULL;
1325 struct GNUNET_MessageHeader * msgheader2 = NULL;
1327 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1328 *(plugin->env->our_hello)) <= WLAN_MTU);
1329 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct RadiotapHeader)
1330 + sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader)
1331 + GNUNET_HELLO_size(*(plugin->env->our_hello));
1333 msgheader = GNUNET_malloc(size);
1334 msgheader->size = htons(size);
1335 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1337 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1338 getRadiotapHeader(radioHeader);
1339 ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
1340 getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
1342 msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1343 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1344 + sizeof(struct GNUNET_MessageHeader));
1346 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1347 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1348 *(plugin->env->our_hello)));
1350 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1352 if (bytes == GNUNET_SYSERR)
1354 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1355 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1356 errno, strerror(errno));
1359 GNUNET_assert(bytes != GNUNET_SYSERR);
1360 GNUNET_assert(bytes == size);
1361 GNUNET_free(msgheader);
1363 set_next_beacon_time(plugin);
1364 check_next_fragment_timeout(plugin);
1368 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1373 struct GNUNET_MessageHeader * msgheader = NULL;
1374 struct IeeeHeader * ieeewlanheader = NULL;
1375 struct RadiotapHeader * radioHeader = NULL;
1376 struct FragmentationAckHeader * msgheader2 = NULL;
1378 GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1381 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1382 "Sending ack for message_id %u with fragment field %u\n",
1383 ack->message_id, ack->fragments_field);
1386 size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct RadiotapHeader)
1387 + sizeof(struct IeeeHeader) + sizeof(struct FragmentationAckHeader);
1388 msgheader = GNUNET_malloc(size);
1389 msgheader->size = htons(size);
1390 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1392 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1393 getRadiotapHeader(radioHeader);
1394 ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
1395 getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
1397 msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1398 msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1399 msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1400 msgheader2->message_id = htonl(ack->message_id);
1401 msgheader2->fragment_field = htonll(ack->fragments_field);
1403 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1404 if (bytes == GNUNET_SYSERR)
1406 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1407 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1408 errno, strerror(errno));
1411 GNUNET_assert(bytes != GNUNET_SYSERR);
1412 GNUNET_assert(bytes == size);
1413 GNUNET_free(msgheader);
1414 check_next_fragment_timeout(plugin);
1418 * Function called when wlan helper is ready to get some data
1420 * @param cls closure
1421 * @param tc GNUNET_SCHEDULER_TaskContext
1425 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1428 struct Plugin * plugin = cls;
1429 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1431 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1434 struct Session * session = NULL;
1435 struct FragmentMessage * fm = NULL;
1436 struct IeeeHeader * ieeewlanheader = NULL;
1437 struct RadiotapHeader * radioHeader = NULL;
1438 struct GNUNET_MessageHeader * msgheader = NULL;
1440 struct FragmentationHeader fragheader;
1441 struct FragmentationHeader * fragheaderptr = NULL;
1442 struct Finish_send * finish = NULL;
1443 struct AckSendQueue * ack;
1446 const char * copystart = NULL;
1447 uint16_t copysize = 0;
1448 uint copyoffset = 0;
1450 if (plugin->ack_send_queue_head != NULL)
1452 ack = plugin->ack_send_queue_head;
1453 GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1454 plugin->ack_send_queue_tail, ack);
1455 send_ack(plugin, ack);
1460 //test if a "hello-beacon" has to be send
1461 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1463 send_hello_beacon(plugin);
1469 fm = plugin->pending_Fragment_Messages_head;
1472 session = fm->session;
1473 GNUNET_assert(session != NULL);
1475 // test if message timed out
1476 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1479 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1482 check_fragment_queue(plugin);
1483 free_fragment_message(plugin, fm);
1489 //if (fm->message_size > WLAN_MTU)
1491 size += sizeof(struct FragmentationHeader);
1493 set_next_message_fragment_pos(fm);
1495 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1500 GNUNET_ERROR_TYPE_DEBUG,
1501 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1502 fm->message_id_out, fm->message_pos, copysize
1503 + sizeof(struct FragmentationHeader), copyoffset,
1504 GNUNET_TIME_absolute_get_remaining(fm->timeout));
1507 fragheader.fragment_off_or_num = htons(fm->message_pos);
1508 fragheader.message_id = htonl(fm->message_id_out);
1509 copystart = fm->msg + copyoffset;
1510 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1511 WLAN_MTU - sizeof(struct FragmentationHeader));
1513 if (copyoffset >= fm->message_size)
1516 GNUNET_ERROR_TYPE_ERROR,
1517 "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1518 copyoffset, fm->message_size, WLAN_MTU
1519 - sizeof(struct FragmentationHeader), copysize,
1522 GNUNET_assert(copyoffset < fm->message_size);
1523 //FIXME remove later
1524 GNUNET_assert(copystart < fm->msg + fm->message_size);
1526 fragheader.header.size = htons(copysize
1527 + sizeof(struct FragmentationHeader));
1528 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1533 // there is no need to split
1534 copystart = fm->msg;
1535 copysize = fm->message_size;
1539 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1540 + sizeof(struct GNUNET_MessageHeader);
1541 msgheader = GNUNET_malloc(size);
1542 msgheader->size = htons(size);
1543 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1545 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1546 getRadiotapHeader(radioHeader);
1548 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1549 getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
1551 //could be faster if content is just send and not copyed before
1552 //fragmentheader is needed
1553 //if (fm->message_size > WLAN_MTU)
1555 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1556 memcpy(&ieeewlanheader[1], &fragheader,
1557 sizeof(struct FragmentationHeader));
1558 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1559 memcpy(&fragheaderptr[1], copystart, copysize);
1563 memcpy(&ieeewlanheader[1], copystart, copysize);
1566 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1568 if (bytes == GNUNET_SYSERR)
1571 GNUNET_ERROR_TYPE_ERROR,
1572 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1573 errno, strerror(errno));
1576 GNUNET_assert(bytes != GNUNET_SYSERR);
1580 finish = GNUNET_malloc(sizeof( struct Finish_send));
1581 finish->plugin = plugin;
1582 finish->msgheader = (char *) msgheader + bytes;
1583 finish->size = size - bytes;
1584 finish->msgstart = msgheader;
1586 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1588 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1589 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1590 &finish_sending, finish);
1595 GNUNET_assert(bytes == size);
1597 GNUNET_free(msgheader);
1598 check_next_fragment_timeout(plugin);
1601 //check if this was the last fragment of this message, if true then queue at the end of the list
1602 if (copysize + copyoffset >= fm->message_size)
1604 GNUNET_assert(copysize + copyoffset == fm->message_size);
1606 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1607 plugin->pending_Fragment_Messages_tail, fm);
1609 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1610 plugin->pending_Fragment_Messages_tail, fm);
1611 // if fragments have opimized timeouts
1612 //sort_fragment_into_queue(plugin,fm);
1619 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1620 "do_transmit did nothing, should not happen!\n");
1624 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1626 struct Finish_send * finish;
1627 struct Plugin * plugin;
1631 plugin = finish->plugin;
1633 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1635 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1636 finish->msgheader, finish->size);
1637 GNUNET_assert(bytes != GNUNET_SYSERR);
1639 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1640 if (bytes != finish->size)
1643 finish->plugin = plugin;
1644 finish->msgheader = finish->msgheader + bytes;
1645 finish->size = finish->size - bytes;
1646 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1647 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1648 &finish_sending, finish);
1652 GNUNET_free(finish->msgstart);
1653 GNUNET_free(finish);
1654 check_next_fragment_timeout(plugin);
1660 getRadiotapHeader(struct RadiotapHeader * Header)
1667 * function to generate the wlan hardware header for one packet
1668 * @param Header address to write the header to
1669 * @param to_mac_addr address of the recipient
1670 * @param plugin pointer to the plugin struct
1671 * @return GNUNET_YES if there was no error
1675 getWlanHeader(struct IeeeHeader * Header, const char * const to_mac_addr,
1676 struct Plugin * plugin)
1678 memcpy(&Header->mac2, macbc, sizeof(macbc));
1679 memcpy(&Header->mac3, plugin->mac_address.mac, sizeof(plugin->mac_address));
1680 memcpy(&Header->mac1, to_mac_addr, sizeof(plugin->mac_address));
1687 * @param msgbuf pointer tor the data
1688 * @param msgbuf_size size of the data
1690 * @return 32bit crc value
1694 getcrc32(const char *msgbuf, size_t msgbuf_size)
1696 //TODO calc some crc
1703 * @param msgbuf pointer tor the data
1704 * @param msgbuf_size size of the data
1706 * @return 16bit crc value
1710 getcrc16(const char *msgbuf, size_t msgbuf_size)
1712 //TODO calc some crc
1717 * Function that can be used by the transport service to transmit
1718 * a message using the plugin.
1720 * @param cls closure
1721 * @param target who should receive this message
1722 * @param priority how important is the message
1723 * @param msgbuf the message to transmit
1724 * @param msgbuf_size number of bytes in 'msgbuf'
1725 * @param timeout when should we time out
1726 * @param session which session must be used (or NULL for "any")
1727 * @param addr the address to use (can be NULL if the plugin
1728 * is "on its own" (i.e. re-use existing TCP connection))
1729 * @param addrlen length of the address in bytes
1730 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1731 * otherwise the plugin may use other addresses or
1732 * existing connections (if available)
1733 * @param cont continuation to call once the message has
1734 * been transmitted (or if the transport is ready
1735 * for the next transmission call; or if the
1736 * peer disconnected...)
1737 * @param cont_cls closure for cont
1738 * @return number of bytes used (on the physical network, with overheads);
1739 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1740 * and does NOT mean that the message was not transmitted (DV)
1743 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1744 const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1745 struct GNUNET_TIME_Relative timeout, struct Session *session,
1746 const void *addr, size_t addrlen, int force_address,
1747 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1749 struct Plugin * plugin = cls;
1750 struct PendingMessage * newmsg = NULL;
1751 struct WlanHeader * wlanheader = NULL;
1753 //check if msglen > 0
1754 GNUNET_assert(msgbuf_size > 0);
1756 //get session if needed
1757 if (session == NULL)
1759 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1761 session = get_Session(plugin, addr);
1765 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1766 _("Wlan Address len %d is wrong\n"), addrlen);
1771 //TODO target "problem" not solved
1772 //if (session->target != NULL){
1773 // GNUNET_assert(session->target == *target);
1775 session->target = *target;
1781 //queue message in session
1782 //test if there is no other message in the "queue"
1783 //FIXME: to many send requests
1784 //GNUNET_assert (session->pending_message == NULL);
1785 if (session->pending_message != NULL)
1787 newmsg = session->pending_message;
1789 GNUNET_ERROR_TYPE_ERROR,
1790 "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",
1791 GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1792 session->fragment_messages_out_count);
1793 if (session->pending_message2 != NULL)
1796 GNUNET_ERROR_TYPE_ERROR,
1797 "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1802 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1803 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1804 wlanheader = (struct WlanHeader *) newmsg->msg;
1805 //copy msg to buffer, not fragmented / segmented yet, but with message header
1806 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1807 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1808 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1809 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1810 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1811 newmsg->transmit_cont = cont;
1812 newmsg->transmit_cont_cls = cont_cls;
1813 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1815 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1817 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1819 if (session->pending_message == NULL)
1821 session->pending_message = newmsg;
1825 session->pending_message2 = newmsg;
1829 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1830 "New message for %p with size (incl wlan header) %u added\n", session,
1831 newmsg->message_size);
1836 queue_Session(plugin, session);
1838 check_fragment_queue(plugin);
1839 //FIXME not the correct size
1845 * function to get the first message in the fragement queue (out) of a session
1846 * @param session pointer to the session
1847 * @return pointer to the struct FragmentMessage
1849 static struct FragmentMessage *
1850 get_fragment_message_from_session(struct Session * session)
1852 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1855 if (fm->session == session)
1865 * function to get the message in the fragement queue (out) of a session with a specific id
1866 * @param session pointer to the session
1867 * @param message_id id of the message
1868 * @return pointer to the struct FragmentMessage
1870 static struct FragmentMessage *
1871 get_fragment_message_from_session_and_id(struct Session * session,
1872 uint32_t message_id)
1874 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1877 if ((fm->session == session) && (fm->message_id_out == message_id))
1887 * Function that can be used to force the plugin to disconnect
1888 * from the given peer and cancel all previous transmissions
1889 * (and their continuation).
1891 * @param cls closure
1892 * @param target peer from which to disconnect
1895 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1897 struct Plugin *plugin = cls;
1898 struct Sessionqueue * queue = plugin->sessions;
1899 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1900 struct PendingMessage * pm = NULL;
1901 struct FragmentMessage * fm;
1902 struct Receive_Message_Queue * receive_queue;
1904 // just look at all the session for the needed one
1905 while (queue != NULL)
1907 // content is never NULL
1908 GNUNET_assert (queue->content != NULL);
1909 if (memcmp(target, &(queue->content->target),
1910 sizeof(struct GNUNET_PeerIdentity)) == 0)
1913 //is this session pending for send
1914 while (pendingsession != NULL)
1916 if (pendingsession->content == queue->content)
1918 plugin->pendingsessions--;
1919 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1920 plugin->pending_Sessions_tail, pendingsession);
1921 GNUNET_free(pendingsession);
1924 pendingsession = pendingsession->next;
1927 //is something of this session in the fragment queue?
1928 fm = get_fragment_message_from_session(queue->content);
1931 free_fragment_message(plugin, fm);
1932 fm = get_fragment_message_from_session(queue->content);
1934 check_next_fragment_timeout(plugin);
1936 //dispose all received fragments
1937 receive_queue = get_receive_message_from_session(plugin,
1939 while (receive_queue != NULL)
1941 free_receive_message(plugin, receive_queue);
1942 receive_queue = get_receive_message_from_session(plugin,
1946 // remove PendingMessage
1947 pm = queue->content->pending_message;
1950 GNUNET_free_non_null(pm->msg);
1954 GNUNET_free(queue->content);
1955 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1957 plugin->session_count--;
1962 queue = queue->next;
1967 * Convert the transports address to a nice, human-readable
1970 * @param cls closure
1971 * @param type name of the transport that generated the address
1972 * @param addr one of the addresses of the host, NULL for the last address
1973 * the specific address format depends on the transport
1974 * @param addrlen length of the address
1975 * @param numeric should (IP) addresses be displayed in numeric form?
1976 * @param timeout after how long should we give up?
1977 * @param asc function to call on each string
1978 * @param asc_cls closure for asc
1981 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1982 const void *addr, size_t addrlen, int numeric,
1983 struct GNUNET_TIME_Relative timeout,
1984 GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1987 const unsigned char * input;
1989 //GNUNET_assert(cls !=NULL);
1992 /* invalid address (MAC addresses have 6 bytes) */
1997 input = (const unsigned char*) addr;
1998 GNUNET_snprintf(ret, sizeof(ret),
1999 "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2000 input[0], input[1], input[2], input[3], input[4], input[5]);
2005 * Another peer has suggested an address for this
2006 * peer and transport plugin. Check that this could be a valid
2007 * address. If so, consider adding it to the list
2010 * @param cls closure
2011 * @param addr pointer to the address
2012 * @param addrlen length of addr
2013 * @return GNUNET_OK if this is a plausible address for this peer
2018 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
2020 //struct Plugin *plugin = cls;
2022 /* check if the address is plausible; if so,
2023 add it to our list! */
2025 GNUNET_assert(cls !=NULL);
2026 //FIXME mitm is not checked
2027 //Mac Address has 6 bytes
2030 /* TODO check for bad addresses like multicast, broadcast, etc */
2035 return GNUNET_SYSERR;
2038 return GNUNET_SYSERR;
2042 * Function called for a quick conversion of the binary address to
2043 * a numeric address. Note that the caller must not free the
2044 * address and that the next call to this function is allowed
2045 * to override the address again.
2047 * @param cls closure
2048 * @param addr binary address
2049 * @param addrlen length of the address
2050 * @return string representing the same address
2053 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
2055 static char ret[40];
2056 const unsigned char * input;
2058 //GNUNET_assert(cls !=NULL);
2061 /* invalid address (MAC addresses have 6 bytes) */
2065 input = (const unsigned char*) addr;
2066 GNUNET_snprintf(ret, sizeof(ret),
2067 "%s Mac-Address %02X:%02X:%02X:%02X:%02X:%02X", PROTOCOL_PREFIX,
2068 input[0], input[1], input[2], input[3], input[4], input[5]);
2073 * function to check if bitfield is representation of fragments of the message
2074 * @param rec_message message to check
2078 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
2080 uint64_t checkfragments = 0;
2081 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2083 while (rec_queue != NULL)
2085 setBit((char*) &checkfragments, rec_queue->num);
2086 rec_queue = rec_queue->next;
2089 GNUNET_assert(checkfragments == rec_message->received_fragments);
2093 * Function to test if fragment number already exists in the fragments received
2095 * @param rec_message message this fragment belongs to
2096 * @param fh Fragmentheader of the fragment
2097 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2101 is_double_msg(struct Receive_Message_Queue * rec_message,
2102 struct FragmentationHeader * fh)
2104 //test if bitfield is okay
2106 check_message_fragment_bitfield(rec_message);
2109 return testBit((char *) &rec_message->received_fragments, ntohs(
2110 fh->fragment_off_or_num));
2115 * Function to insert a fragment in a queue of a message
2116 * @param session session the fragment belongs to
2117 * @param rec_queue fragment to add
2121 insert_fragment_in_queue(struct Receive_Message_Queue * rec_message,
2122 struct Receive_Fragment_Queue * rec_queue)
2124 struct Receive_Fragment_Queue * rec_queue2 = rec_message->frag_head;
2125 struct WlanHeader * wlanheader = NULL;
2127 GNUNET_assert(rec_message != NULL);
2128 GNUNET_assert(rec_queue != NULL);
2130 //this is the first fragment of the message (fragment id 0)
2131 if (rec_queue->num == 0)
2133 wlanheader = (struct WlanHeader *) rec_queue->msg;
2134 rec_message->rec_size = ntohs(wlanheader->header.size);
2138 while (rec_queue2 != NULL)
2140 if (rec_queue2->num > rec_queue->num)
2142 //next element number is grater than the current num
2143 GNUNET_CONTAINER_DLL_insert_before(rec_message->frag_head, rec_message->frag_tail, rec_queue2, rec_queue);
2144 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2147 rec_queue = rec_queue->next;
2149 //no element has a grater number
2150 GNUNET_CONTAINER_DLL_insert_tail(rec_message->frag_head, rec_message->frag_tail, rec_queue);
2152 setBit((char *) &rec_message->received_fragments, rec_queue->num);
2156 * Function to dispose the fragments received for a message and the message
2157 * @param session session to free the fragments from
2161 free_receive_message(struct Plugin* plugin,
2162 struct Receive_Message_Queue * rec_message)
2164 GNUNET_assert(rec_message !=NULL);
2165 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2166 struct Receive_Fragment_Queue * rec_queue2;
2168 while (rec_queue != NULL)
2170 rec_queue2 = rec_queue;
2171 rec_queue = rec_queue->next;
2172 GNUNET_free(rec_queue2);
2175 GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rec_message);
2177 GNUNET_assert(plugin->pending_receive_messages > 0);
2178 GNUNET_assert(rec_message->session->fragment_messages_in_count > 0);
2180 plugin->pending_receive_messages--;
2181 rec_message->session->fragment_messages_in_count--;
2182 GNUNET_free(rec_message);
2186 * Function to check if all fragments of a message have been received
2187 * @param plugin the plugin handle
2188 * @param session_light information of the message sender
2189 * @param session session the message belongs to
2193 check_rec_finished_msg(struct Plugin* plugin,
2194 struct Session_light * session_light, struct Session * session,
2195 struct Receive_Message_Queue * rec_message)
2197 struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
2198 int packetsize = rec_message->rec_size;
2201 uint64_t bitfield = 0;
2204 GNUNET_assert(rec_message !=NULL);
2205 //check if first fragment is present
2206 if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2211 check_message_fragment_bitfield(rec_message);
2214 bitfield = ~bitfield;
2215 bitfield = bitfield >> (63 - rec_message->frag_tail->num);
2216 if (rec_message->received_fragments == bitfield)
2219 while (rec_queue != NULL)
2221 sum += rec_queue->size;
2222 rec_queue = rec_queue->next;
2224 //sum should always be smaller or equal of
2225 GNUNET_assert(sum <= packetsize);
2226 if (sum == packetsize)
2230 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2231 "check_rec_finished_msg: A message for %p is complete\n", session);
2235 //copy fragments together
2236 msg = GNUNET_malloc(packetsize);
2237 rec_queue = rec_message->frag_head;
2239 while (rec_queue != NULL)
2241 //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2242 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
2243 aktnum += rec_queue->size;
2244 rec_queue = rec_queue->next;
2246 free_receive_message(plugin, rec_message);
2247 //call wlan_process_helper to process the message
2248 wlan_data_massage_handler(plugin, session_light,
2249 (struct GNUNET_MessageHeader*) msg);
2250 //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2258 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2261 GNUNET_assert(client != NULL);
2262 GNUNET_assert(cls != NULL);
2263 struct Session * session = (struct Session *) client;
2264 struct Plugin * plugin = (struct Plugin *) cls;
2266 struct GNUNET_TRANSPORT_ATS_Information distance[2];
2267 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2268 distance[0].value = htonl(1);
2269 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2270 distance[1].value = htonl(0);
2273 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2274 "Calling plugin->env->receive for session %p; %s\n", session,
2275 wlan_plugin_address_to_string(NULL, session->addr, 6));
2278 plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2279 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2280 session->addr, sizeof(session->addr));
2284 * handels the data after all fragments are put together
2286 * @param session_light
2287 * @param hdr pointer to the data
2290 wlan_data_massage_handler(struct Plugin * plugin,
2291 struct Session_light * session_light,
2292 const struct GNUNET_MessageHeader * hdr)
2294 struct WlanHeader * wlanheader = NULL;
2295 struct Session * session = NULL;
2296 const char * tempmsg = NULL;
2297 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2298 struct GNUNET_PeerIdentity tmptarget;
2300 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2305 GNUNET_ERROR_TYPE_DEBUG,
2306 "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2310 GNUNET_assert(session_light != NULL);
2311 if (session_light->session == NULL)
2313 session_light->session = search_session(plugin, session_light->addr);
2315 session = session_light->session;
2316 wlanheader = (struct WlanHeader *) hdr;
2317 tempmsg = (char*) &wlanheader[1];
2318 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2320 if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2323 //wrong crc, dispose message
2324 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2325 "Wlan message Header crc was wrong\n");
2329 //if not in session list
2330 if (session == NULL)
2334 GNUNET_ERROR_TYPE_DEBUG,
2335 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2336 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2337 sizeof(struct WlanHeader));
2339 //try if it is a hello message
2340 if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2341 + sizeof(struct WlanHeader))
2343 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2345 if (GNUNET_HELLO_get_id(
2346 (const struct GNUNET_HELLO_Message *) temp_hdr,
2347 &tmptarget) == GNUNET_OK)
2349 session = create_session(plugin, session_light->addr);
2350 session_light->session = session;
2351 memcpy(&session->target, &tmptarget,
2352 sizeof(struct GNUNET_PeerIdentity));
2356 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2357 "WLAN client not in session list and hello message not okay\n");
2364 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2365 "WLAN client not in session list and not a hello message\n");
2372 GNUNET_ERROR_TYPE_WARNING,
2373 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2374 ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2375 sizeof(struct WlanHeader));
2380 //"receive" the message
2383 GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2384 (const char *) temp_hdr,
2385 ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2391 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2392 "wlan_data_massage_handler got wrong message type\n");
2398 * function to add an ack to send it for a received fragment
2399 * @param plugin pointer to the global plugin structure
2400 * @param session pointer to the session this ack belongs to
2401 * @param fh pointer to the fragmentation header which we would like to acknolage
2405 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2406 uint64_t bitfield, struct FragmentationHeader * fh)
2408 struct AckSendQueue * ack;
2410 GNUNET_assert(plugin != NULL);
2411 GNUNET_assert(session != NULL);
2412 GNUNET_assert(fh != NULL);
2414 ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2415 ack->fragments_field = bitfield;
2416 ack->message_id = ntohl(fh->message_id);
2417 ack->session = session;
2419 GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2420 plugin->ack_send_queue_tail, ack);
2425 * function to get the receive message from the message id and the session
2426 * @param plugin pointer to the plugin struct
2427 * @param session session this fragment belongs to
2428 * @param message_id id of the message
2431 struct Receive_Message_Queue *
2432 get_receive_message(struct Plugin * plugin, struct Session * session,
2433 uint32_t message_id)
2435 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2436 while (rec_message != NULL)
2438 if ((rec_message->message_id_in == message_id) && (rec_message->session
2443 rec_message = rec_message->next;
2449 * function to get the receive message of a session
2450 * @param plugin pointer to the plugin struct
2451 * @param session session this fragment belongs to
2454 struct Receive_Message_Queue *
2455 get_receive_message_from_session(struct Plugin * plugin,
2456 struct Session * session)
2458 struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2459 while (rec_message != NULL)
2461 if (rec_message->session == session)
2465 rec_message = rec_message->next;
2471 * function to insert a received fragment into the right fragment queue of the right message
2472 * @param plugin pointer to the plugin struct
2473 * @param session session this fragment belongs to
2474 * @param fh pointer to the header of the fragment
2475 * @return new fragment bitfield for the message
2479 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2480 struct Session_light * session_light, struct Session * session,
2481 struct FragmentationHeader * fh)
2483 struct Receive_Fragment_Queue * rec_queue = NULL;
2484 struct Receive_Message_Queue * rec_message;
2485 const char * tempmsg = (char*) &fh[1];
2486 uint64_t retval = 0;
2488 //TODO fragments do not timeout
2489 //check if message_id is right or it is a new msg
2490 GNUNET_assert(fh != NULL);
2492 rec_message = get_receive_message(plugin, session, ntohs(fh->message_id));
2494 if (rec_message == NULL)
2496 if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2499 //new message incoming
2500 rec_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2501 rec_message->message_id_in = ntohs(fh->message_id);
2502 rec_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2503 rec_message->session = session;
2504 rec_message->timeout = GNUNET_TIME_absolute_add(
2505 GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2506 rec_message->received_fragments = 0;
2508 GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rec_message);
2510 session->fragment_messages_in_count++;
2511 plugin->pending_receive_messages++;
2515 GNUNET_ERROR_TYPE_DEBUG,
2516 "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2517 rec_message->message_id_in, session->fragment_messages_in_count,
2518 plugin->pending_receive_messages);
2525 GNUNET_ERROR_TYPE_INFO,
2526 "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2527 setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2532 if (is_double_msg(rec_message, fh) != GNUNET_YES)
2536 rec_queue = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2537 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2538 rec_queue->size = ntohs(fh->header.size)
2539 - sizeof(struct FragmentationHeader);
2540 rec_queue->num = ntohs(fh->fragment_off_or_num);
2541 rec_queue->msg = (char*) &(rec_queue[1]);
2542 //copy msg to buffer
2543 memcpy((char *)rec_queue->msg, tempmsg, rec_queue->size);
2544 insert_fragment_in_queue(rec_message, rec_queue);
2546 retval = rec_message->received_fragments;
2550 GNUNET_ERROR_TYPE_DEBUG,
2551 "New fragment: size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2552 rec_message->rec_size, rec_queue->size,
2553 rec_message->received_fragments, rec_message->message_id_in, session);
2556 check_rec_finished_msg(plugin, session_light, session, rec_message);
2560 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2561 retval = rec_message->received_fragments;
2569 * Function used for to process the data received from the wlan interface
2571 * @param cls the plugin handle
2572 * @param session_light FIXME: document
2573 * @param hdr hdr of the GNUNET_MessageHeader
2576 wlan_data_helper(void *cls, struct Session_light * session_light,
2577 const struct GNUNET_MessageHeader * hdr)
2579 struct Plugin *plugin = cls;
2580 struct Session * session = NULL;
2582 struct FragmentationHeader * fh = NULL;
2583 struct FragmentationAckHeader * fah = NULL;
2584 struct FragmentMessage * fm = NULL;
2586 const char * tempmsg = NULL;
2588 uint64_t fragment_bitfield = 0;
2591 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2594 //TODO better DOS protection, error handling
2595 //TODO test first than create session
2596 GNUNET_assert(session_light != NULL);
2600 GNUNET_ERROR_TYPE_DEBUG,
2601 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2602 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2603 session_light->addr, 6));
2606 if (session_light->session == NULL)
2608 session_light->session = get_Session(plugin, session_light->addr);
2610 GNUNET_assert(GNUNET_HELLO_get_id(
2611 (const struct GNUNET_HELLO_Message *) &hdr[1],
2612 &(session_light->session->target) ) != GNUNET_SYSERR);
2617 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2620 GNUNET_assert(session_light != NULL);
2621 if (session_light->session == NULL)
2623 session_light->session = search_session(plugin, session_light->addr);
2625 session = session_light->session;
2627 fh = (struct FragmentationHeader *) hdr;
2628 tempmsg = (char*) &fh[1];
2632 GNUNET_ERROR_TYPE_DEBUG,
2633 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2634 ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2635 hdr->size), wlan_plugin_address_to_string(NULL,
2636 session_light->addr, 6));
2639 if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2641 //wrong crc, dispose message
2642 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2646 //if in the session list
2647 if (session != NULL)
2649 fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2650 session_light, session, fh);
2656 GNUNET_ERROR_TYPE_INFO,
2657 "WLAN client not in session list, fragment num %u, message id %u\n",
2658 ntohs(fh->fragment_off_or_num), ntohs(fh->message_id));
2659 wlan_data_massage_handler(plugin, session_light,
2660 (struct GNUNET_MessageHeader *) tempmsg);
2661 session = session_light->session;
2662 //test if a session was created
2663 if (session == NULL)
2667 setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2670 add_ack_for_send(plugin, session, fragment_bitfield, fh);
2671 check_next_fragment_timeout(plugin);
2676 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2681 GNUNET_ERROR_TYPE_DEBUG,
2682 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2683 ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2684 session_light->addr, 6));
2687 GNUNET_assert(session_light != NULL);
2688 if (session_light->session == NULL)
2690 session_light->session = search_session(plugin, session_light->addr);
2691 GNUNET_assert(session_light->session != NULL);
2693 session = session_light->session;
2694 fah = (struct FragmentationAckHeader *) hdr;
2695 fm = get_fragment_message_from_session_and_id(session, ntohl(
2700 fm->ack_bitfield = fm->ack_bitfield | ntohll(fah->fragment_field);
2701 check_finished_fragment(plugin, fm);
2705 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2706 "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2715 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2716 "WLAN packet inside the WLAN helper packet has not the right type\n");
2721 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2722 "Helper finished\n");
2728 macprinter(struct MacAddress macx)
2730 static char macstr[20];
2731 char * mac = macx.mac;
2732 sprintf(macstr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac[0], mac[1], mac[2],
2733 mac[3], mac[4], mac[5]);
2738 * Function used for to process the data from the suid process
2740 * @param cls the plugin handle
2741 * @param client client that send the data (not used)
2742 * @param hdr header of the GNUNET_MessageHeader
2746 wlan_process_helper(void *cls, void *client,
2747 const struct GNUNET_MessageHeader *hdr)
2749 struct Plugin *plugin = cls;
2750 struct IeeeHeader * wlanIeeeHeader = NULL;
2751 struct Session_light * session_light = NULL;
2752 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2757 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
2761 GNUNET_ERROR_TYPE_DEBUG,
2762 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2766 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2767 GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader));
2768 wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
2770 //process only if it is an broadcast or for this computer both with the gnunet bssid
2773 if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress))
2776 //check for broadcast or mac
2777 if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac,
2778 sizeof(struct MacAddress) == 0) || memcmp(
2779 &(wlanIeeeHeader->mac1), &(plugin->mac_address),
2780 sizeof(struct MacAddress)) == 0)
2783 // process the inner data
2786 datasize = ntohs(hdr->size) - sizeof(struct IeeeHeader)
2787 - sizeof(struct GNUNET_MessageHeader);
2789 session_light = GNUNET_malloc(sizeof(struct Session_light));
2790 memcpy(session_light->addr, &(wlanIeeeHeader->mac3),
2791 sizeof(struct MacAddress));
2792 //session_light->session = search_session(plugin,session_light->addr);
2795 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2796 while (pos < datasize)
2798 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2801 wlan_data_helper(plugin, session_light, temp_hdr);
2802 pos += ntohs(temp_hdr->size);
2807 GNUNET_free(session_light);
2812 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2813 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2814 wlanIeeeHeader->mac1));
2821 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2822 "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2823 wlanIeeeHeader->mac2));
2829 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
2834 GNUNET_ERROR_TYPE_DEBUG,
2835 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %u\n",
2839 //TODO more control messages
2840 //TODO use struct wlan_helper_control
2841 if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
2843 //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
2844 memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
2845 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2846 "Notifying transport of address %s\n",
2847 wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(
2848 hdr->size) - sizeof(struct GNUNET_MessageHeader)));
2849 plugin->env->notify_address(plugin->env->cls, "wlan",
2850 &plugin->mac_address, sizeof(struct MacAddress),
2851 GNUNET_TIME_UNIT_FOREVER_REL);
2855 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
2856 macprinter(plugin->mac_address));
2864 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2865 "WLAN helper packet has not the right type\n");
2871 * We have been notified that wlan-helper has written something to stdout.
2872 * Handle the output, then reschedule this function to be called again once
2873 * more is available.
2875 * @param cls the plugin handle
2876 * @param tc the scheduling context
2880 wlan_plugin_helper_read(void *cls,
2881 const struct GNUNET_SCHEDULER_TaskContext *tc)
2883 struct Plugin *plugin = cls;
2884 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2889 "Start reading from STDIN\n");
2892 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2895 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2898 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2903 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2904 _("Finished reading from wlan-helper stdout with code: %d\n"),
2909 GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2910 GNUNET_NO, GNUNET_NO);
2912 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2913 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2914 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2915 &wlan_plugin_helper_read, plugin);
2919 * Start the gnunet-wlan-helper process.
2921 * @param plugin the transport plugin
2922 * @param testmode should we use the dummy driver for testing?
2923 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2926 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2928 const char * filename = "gnunet-transport-wlan-helper";
2929 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2930 if (plugin->server_stdout == NULL)
2931 return GNUNET_SYSERR;
2933 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2934 if (plugin->server_stdin == NULL)
2935 return GNUNET_SYSERR;
2938 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2939 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2940 plugin->interface, testmode);
2942 /* Start the server process */
2944 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2945 plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2946 == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2947 if (plugin->server_proc == NULL)
2950 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2951 "Failed to start gnunet-wlan-helper process\n");
2953 return GNUNET_SYSERR;
2956 /* Close the write end of the read pipe */
2957 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2959 /* Close the read end of the write pipe */
2960 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2962 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2963 GNUNET_DISK_PIPE_END_READ);
2964 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2965 GNUNET_DISK_PIPE_END_WRITE);
2967 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2970 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2971 "Adding server_read_task for the wlan-helper\n");
2976 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2977 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2978 &wlan_plugin_helper_read, plugin);
2984 * Exit point from the plugin.
2985 * @param cls pointer to the api struct
2990 libgnunet_plugin_transport_wlan_done(void *cls)
2992 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2993 struct Plugin *plugin = api->cls;
2996 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2997 "libgnunet_plugin_transport_wlan_done started\n");
3000 GNUNET_assert(cls !=NULL);
3002 if (plugin->suid_tokenizer != NULL)
3003 GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
3005 if (plugin->data_tokenizer != NULL)
3006 GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3008 GNUNET_free_non_null(plugin->interface);
3009 GNUNET_free (plugin);
3015 * Entry point for the plugin.
3017 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3018 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3021 libgnunet_plugin_transport_wlan_init(void *cls)
3023 //struct GNUNET_SERVICE_Context *service;
3024 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3025 struct GNUNET_TRANSPORT_PluginFunctions *api;
3026 struct Plugin *plugin;
3027 static unsigned long long testmode = 0;
3029 GNUNET_assert(cls !=NULL);
3031 plugin = GNUNET_malloc (sizeof (struct Plugin));
3033 plugin->pendingsessions = 0;
3034 plugin->session_count = 0;
3035 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3036 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3037 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3039 set_next_beacon_time(plugin);
3041 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3043 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3044 "transport-wlan", "TESTMODE", &testmode))
3048 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3050 if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3051 "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3053 libgnunet_plugin_transport_wlan_done(plugin);
3058 wlan_transport_start_wlan_helper(plugin, testmode);
3059 plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3062 plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3064 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3065 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3067 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3069 api->send = &wlan_plugin_send;
3070 api->disconnect = &wlan_plugin_disconnect;
3071 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3072 api->check_address = &wlan_plugin_address_suggested;
3073 api->address_to_string = &wlan_plugin_address_to_string;
3075 start_next_message_id();
3078 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3084 /* end of plugin_transport_wlan.c */