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
52 #define DEBUG_wlan GNUNET_YES
54 #define MESSAGE_LENGHT_UNKNOWN -1
55 #define NO_MESSAGE_OR_MESSAGE_FINISHED -2
59 * After how long do we expire an address that we
60 * learned from another peer if it is not reconfirmed
63 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
66 * Initial handshake message for a session.
71 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
73 struct GNUNET_MessageHeader header;
76 * Identit*mac_y of the node connecting (TCP client)
78 struct GNUNET_PeerIdentity clientIdentity;
84 * Encapsulation of all of the state of the plugin.
91 struct GNUNET_TRANSPORT_PluginEnvironment *env;
94 * List of open sessions. head
96 struct Sessionqueue *sessions;
99 * List of open sessions. tail
101 struct Sessionqueue *sessions_tail;
110 * encapsulation to the local wlan server prog
113 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
117 * stdout pipe handle for the gnunet-wlan-helper process
119 struct GNUNET_DISK_PipeHandle *server_stdout;
122 * stdout file handle for the gnunet-wlan-helper process
124 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
127 * stdin pipe handle for the gnunet-wlan-helper process
129 struct GNUNET_DISK_PipeHandle *server_stdin;
132 * stdin file handle for the gnunet-wlan-helper process
134 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
137 * ID of the gnunet-wlan-server std read task
139 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
142 * ID of the gnunet-wlan-server std read task
144 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
147 * ID of the delay task for writing
149 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
152 * The process id of the wlan process
154 struct GNUNET_OS_Process *server_proc;
157 * The interface of the wlan card given to us by the user.
162 * The mac_address of the wlan card given to us by the helper.
164 struct MacAddress mac_address;
167 * Sessions currently pending for transmission
168 * to this peer, if any.
170 struct Sessionqueue * pending_Sessions;
173 * Sessions currently pending for transmission
174 * to this peer (tail), if any.
176 struct Sessionqueue * pending_Sessions_tail;
179 * number of pending sessions
181 unsigned int pendingsessions;
184 * Messages in the fragmentation queue, head
187 struct FragmentMessage * pending_Fragment_Messages_head;
190 * Messages in the fragmentation queue, tail
193 struct FragmentMessage * pending_Fragment_Messages_tail;
196 * number of pending fragment message
199 unsigned int pending_fragment_messages;
202 * time of the next "hello-beacon"
205 struct GNUNET_TIME_Absolute beacon_time;
211 struct Plugin * plugin;
213 struct GNUNET_MessageHeader * msgstart;
218 * Queue of sessions, for the general session queue and the pending session queue
223 struct Sessionqueue * next;
224 struct Sessionqueue * prev;
225 struct Session * content;
229 * Queue of ack received for messages send
234 struct AckQueue * next;
235 struct AckQueue * prev;
236 int fragment_num; //TODO change it to offset if better
242 * Queue for the fragments received
247 struct RecQueue * next;
248 struct RecQueue * prev;
255 * Information kept for each message that is yet to
258 struct PendingMessage
262 * The pending message
267 * Continuation function to call once the message
268 * has been sent. Can be NULL if there is no
269 * continuation to call.
271 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
274 * Cls for transmit_cont
276 void * transmit_cont_cls;
279 * Timeout value for the pending message.
281 struct GNUNET_TIME_Absolute timeout;
284 * Size of the message
291 * Session infos gathered from a messages
297 * the session this message belongs to
299 struct Session * session;
307 * Session handle for connections.
315 struct SessionHeader header;
318 * Pointer to the global plugin struct.
320 struct Plugin *plugin;
323 * Message currently pending for transmission
324 * to this peer, if any.
326 struct PendingMessage *pending_message;
329 * To whom are we talking to (set to our identity
330 * if we are still waiting for the welcome message)
332 struct GNUNET_PeerIdentity target;
335 * encapsulation of the receive data
337 //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
340 * offset of the next fragment for the receive_token, -1 means last message finished
346 * size of the message received,
347 * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
348 * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
354 * Sorted queue with the fragments received; head
357 struct RecQueue * frag_head;
360 * Sorted queue with the fragments received; tail
363 struct RecQueue * frag_tail;
371 * Address of the other peer (either based on our 'connect'
372 * call or on our 'accept' call).
377 * Last activity on this connection. Used to select preferred
380 struct GNUNET_TIME_Absolute last_activity;
383 * current number for message incoming, to distinguish between the messages
385 uint32_t message_id_in;
388 * current number for message outgoing, to distinguish between the messages
390 uint32_t message_id_out;
393 * does this session have a message in the fragment queue
403 struct FragmentMessage
406 * Session this message belongs to
409 struct Session *session;
412 * This is a doubly-linked list.
414 struct FragmentMessage *next;
417 * This is a doubly-linked list.
419 struct FragmentMessage *prev;
422 * The pending message
427 * Timeout value for the pending message.
429 struct GNUNET_TIME_Absolute timeout;
432 * Timeout value for the pending fragments.
433 * Stores the time when the next msg fragment ack has to be received
435 struct GNUNET_TIME_Absolute next_ack;
438 * Sorted queue with the acks received for fragments; head
441 struct AckQueue * head;
444 * Sorted queue with the acks received for fragments; tail
447 struct AckQueue * tail;
450 * Size of the message
455 * pos / next fragment number in the message, for fragmentation/segmentation,
456 * some acks can be missing but there is still time
458 uint32_t message_pos;
463 * Header for messages which need fragmentation
468 struct GNUNET_MessageHeader header;
471 * checksum/error correction
473 uint32_t crc GNUNET_PACKED;
476 * To whom are we talking to (set to our identity
477 * if we are still waiting for the welcome message)
479 struct GNUNET_PeerIdentity target;
481 // followed by payload
486 * Header for messages which need fragmentation
488 struct FragmentationHeader
491 struct GNUNET_MessageHeader header;
494 * To whom are we talking to (set to our identity
495 * if we are still waiting for the welcome message)
497 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
500 * ID of message, to distinguish between the messages, picked randomly.
502 uint32_t message_id GNUNET_PACKED;
505 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
507 uint16_t fragment_off_or_num GNUNET_PACKED;
510 * CRC of fragment (for error checking)
512 uint16_t message_crc GNUNET_PACKED;
516 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
517 * // 0x2 has data (not only ack)
518 * // 0x4 last fragment of message
521 // uint32_t flags GNUNET_PACKED;
524 * checksum/error correction
526 // uint32_t crc GNUNET_PACKED;
528 // followed by payload unless ACK
532 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
535 getRadiotapHeader(struct RadiotapHeader * Header);
538 getWlanHeader(struct IeeeHeader * Header);
541 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
544 getcrc16(const char *msgbuf, size_t msgbuf_size);
547 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
550 check_fragment_queue(struct Plugin * plugin);
553 getcrc32(const char *msgbuf, size_t msgbuf_size);
556 free_rec_frag_queue(struct Session * session);
559 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr);
562 wlan_process_helper (void *cls,
564 const struct GNUNET_MessageHeader *hdr);
567 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
570 * get the next message number, at the moment just a random one
571 * @return returns the next valid message-number for sending packets
574 get_next_message_id()
576 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
580 * start next message number generator
581 * (not necessary at the moment)
584 start_next_message_id()
586 //GNUNET_CRYPTO_random_init;
590 * search for a session with the addr
592 * @param plugin pointer to the plugin struct
593 * @param addr pointer to the mac address of the peer
594 * @return returns the session
597 static struct Session *
598 search_session(struct Plugin *plugin, const uint8_t * addr)
600 struct Sessionqueue * queue = plugin->sessions;
601 struct Sessionqueue * lastitem = NULL;
603 //just look at all the session for the needed one
604 while (queue != NULL)
606 // content is never NULL
607 GNUNET_assert (queue->content != NULL);
608 char * addr2 = queue->content->addr;
609 if (memcmp(addr, addr2, 6) == 0)
612 return queue->content;
622 * create a new session
624 * @param plugin pointer to the plugin struct
625 * @param addr pointer to the mac address of the peer
626 * @return returns the session
629 static struct Session *
630 create_session(struct Plugin *plugin,const uint8_t * addr)
632 struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
634 GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
636 queue->content = GNUNET_malloc (sizeof (struct Session));
637 queue->content->plugin = plugin;
638 memcpy(queue->content->addr, addr, 6);
639 queue->content->message_id_out = get_next_message_id();
640 queue->content->has_fragment = 0;
641 queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
643 plugin->session_count++;
644 return queue->content;
648 * get Session from address, create if no session exists
650 * @param plugin pointer to the plugin struct
651 * @param addr pointer to the mac address of the peer
652 * @return returns the session
654 //TODO add other possibilities to find the right session (are there other?)
655 static struct Session *
656 get_Session(struct Plugin *plugin, const uint8_t * addr)
658 struct Session * session = search_session(plugin, addr);
664 return create_session(plugin, addr);
666 /* -- not needed, layer above already has it--
667 //queue welcome message for new sessions, not realy needed
668 //struct WelcomeMessage welcome;
669 struct PendingMessage *pm;
670 pm = GNUNET_malloc (sizeof (struct PendingMessage));
671 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
672 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
673 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
674 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
675 //welcome.clientIdentity = *plugin->env->my_identity;
676 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
677 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
678 queue->content->pending_message = pm;
679 plugin->pendingsessions ++;
680 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
682 check_fragment_queue(plugin);
687 * Queue the session to send data
691 queue_Session (struct Plugin *plugin,
692 struct Session * session)
694 struct Sessionqueue * queue = plugin->pending_Sessions;
695 struct Sessionqueue * lastitem = NULL;
697 while (queue != NULL){
698 // content is never NULL
699 GNUNET_assert (queue->content == NULL);
700 // is session already in queue?
701 if (session == queue->content){
709 // Session is not in the queue
711 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
712 queue->content = session;
715 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
716 plugin->pending_Sessions_tail,
717 plugin->pending_Sessions_tail, queue);
718 plugin->pendingsessions ++;
724 free_acks (struct FragmentMessage * fm){
725 struct AckQueue * fq;
726 while (fm->head != NULL){
728 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
738 * Function to schedule the write task, executed after a delay
741 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
743 struct Plugin * plugin = cls;
744 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
746 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
749 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
750 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
752 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
753 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
754 &do_transmit, plugin);
760 * Function to calculate the time of the next periodic "hello-beacon"
763 set_next_beacon_time(struct Plugin * const plugin)
765 //under 10 known peers: once a second
766 if (plugin->session_count < 10)
768 plugin->beacon_time = GNUNET_TIME_absolute_add(
769 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
771 //under 30 known peers: every 10 seconds
772 else if (plugin->session_count < 30)
774 plugin->beacon_time = GNUNET_TIME_absolute_add(
775 GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
776 GNUNET_TIME_UNIT_SECONDS, 10));
778 //over 30 known peers: once a minute
781 plugin->beacon_time = GNUNET_TIME_absolute_add(
782 GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
788 struct GNUNET_TIME_Relative
789 get_next_frag_timeout(struct FragmentMessage * fm)
791 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
792 fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
797 * Function to get the timeout value for acks for this session
800 struct GNUNET_TIME_Relative
801 get_ack_timeout (struct FragmentMessage * fm){
802 return FRAGMENT_TIMEOUT;
807 * Function to set the timer for the next timeout of the fragment queue
808 * @param plugin the handle to the plugin struct
811 check_next_fragment_timeout(struct Plugin * const plugin)
813 struct FragmentMessage * fm;
814 struct GNUNET_TIME_Relative next_send;
816 next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
819 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
821 GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
823 fm = plugin->pending_Fragment_Messages_head;
825 GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
827 //check if there are some fragments in the queue
831 = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
833 plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
834 &delay_fragment_task, plugin);
841 * Function to get the next queued Session, removes the session from the queue
844 static struct Session *
845 get_next_queue_Session (struct Plugin * plugin){
846 struct Session * session;
847 struct Sessionqueue * sessionqueue;
848 struct Sessionqueue * sessionqueue_alt;
849 struct PendingMessage * pm;
850 sessionqueue = plugin->pending_Sessions;
851 while (sessionqueue != NULL){
852 session = sessionqueue->content;
853 pm = session->pending_message;
855 //check for message timeout
856 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
857 //check if session has no message in the fragment queue
858 if (! session->has_fragment){
859 plugin->pendingsessions --;
860 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
861 plugin->pending_Sessions_tail, sessionqueue);
862 GNUNET_free(sessionqueue);
866 sessionqueue = sessionqueue->next;
870 session->pending_message = NULL;
871 //call the cont func that it did not work
872 if (pm->transmit_cont != NULL)
873 pm->transmit_cont (pm->transmit_cont_cls,
874 &(session->target), GNUNET_SYSERR);
875 GNUNET_free(pm->msg);
878 sessionqueue_alt = sessionqueue;
879 sessionqueue = sessionqueue->next;
880 plugin->pendingsessions --;
881 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
882 plugin->pending_Sessions_tail, sessionqueue_alt);
884 GNUNET_free(sessionqueue_alt);
895 * Function to sort the message into the message fragment queue
896 * @param plugin the plugin struct
897 * @param fm message to sort into the queue
900 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
901 struct FragmentMessage * fm2;
902 //sort into the list at the right position
904 fm2 = plugin->pending_Fragment_Messages_head;
907 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
914 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
915 plugin->pending_Fragment_Messages_tail,fm2,fm);
919 * frees the space of a message in the fragment queue (send queue)
920 * @param plugin the plugin struct
921 * @param fm message to free
924 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
929 GNUNET_free_non_null(fm->msg);
930 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
931 plugin->pending_Fragment_Messages_tail, fm);
933 plugin->pending_fragment_messages --;
934 check_fragment_queue(plugin);
939 * Function to check if there is some space in the fragment queue
940 * inserts a message if space is available
941 * @param plugin the plugin struct
945 check_fragment_queue (struct Plugin * plugin){
946 struct Session * session;
947 struct FragmentMessage * fm;
949 struct PendingMessage * pm;
951 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
952 session = get_next_queue_Session(plugin);
953 if (session != NULL){
954 pm = session->pending_message;
955 session->pending_message = NULL;
956 session->has_fragment = 1;
957 GNUNET_assert(pm != NULL);
959 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
960 fm->message_size = pm->message_size;
962 fm->session = session;
963 fm->timeout.abs_value = pm->timeout.abs_value;
965 fm->next_ack = GNUNET_TIME_absolute_get();
967 if (pm->transmit_cont != NULL)
968 pm->transmit_cont (pm->transmit_cont_cls,
969 &(session->target), GNUNET_OK);
972 sort_fragment_into_queue(plugin,fm);
973 plugin->pending_fragment_messages ++;
975 //generate new message id
976 session->message_id_out = get_next_message_id();
978 //check if timeout changed
979 check_next_fragment_timeout(plugin);
985 * Funktion to check if all fragments where send and the acks received
986 * frees the space if finished
987 * @param plugin the plugin struct
988 * @param fm the message to check
991 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
992 struct AckQueue * ack;
995 if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
996 * fm->tail->fragment_num)
1000 //check if all acks are present
1003 if (counter == ack->fragment_num)
1012 fm->session->has_fragment = 0;
1013 free_fragment_message(plugin, fm);
1020 * Function called when wlan helper is ready to get some data
1022 * @param cls closure
1023 * @param tc GNUNET_SCHEDULER_TaskContext
1027 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1030 struct Plugin * plugin = cls;
1031 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1035 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1038 struct Session * session = NULL;
1039 struct FragmentMessage * fm = NULL;
1040 struct IeeeHeader * ieeewlanheader = NULL;
1041 struct RadiotapHeader * radioHeader = NULL;
1042 struct GNUNET_MessageHeader * msgheader = NULL;
1044 struct FragmentationHeader fragheader;
1045 struct FragmentationHeader * fragheaderptr = NULL;
1046 struct Finish_send * finish = NULL;
1048 const char * copystart = NULL;
1049 uint16_t copysize = 0;
1050 uint copyoffset = 0;
1051 struct AckQueue * akt = NULL;
1054 struct GNUNET_MessageHeader * msgheader2 = NULL;
1056 //test if a "hello-beacon" has to be send
1057 if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1059 //check if the message is not to big
1060 GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1061 *(plugin->env->our_hello)) <= WLAN_MTU);
1062 size = sizeof(struct GNUNET_MessageHeader)
1063 + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1064 + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1065 *(plugin->env->our_hello));
1067 msgheader = GNUNET_malloc(size);
1068 msgheader->size = htons(size);
1069 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1071 radioHeader = (struct RadiotapHeader *) &msgheader[1];
1072 getRadiotapHeader(radioHeader);
1074 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1075 getWlanHeader(ieeewlanheader);
1077 msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1078 msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1079 + sizeof(struct GNUNET_MessageHeader));
1080 msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1082 memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1083 *(plugin->env->our_hello)));
1085 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1087 if (bytes == GNUNET_SYSERR)
1089 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1090 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1091 errno, strerror(errno));
1094 GNUNET_assert(bytes != GNUNET_SYSERR);
1095 GNUNET_assert(bytes == size);
1097 GNUNET_free(msgheader);
1099 set_next_beacon_time(plugin);
1100 check_next_fragment_timeout(plugin);
1108 fm = plugin->pending_Fragment_Messages_head;
1109 GNUNET_assert(fm != NULL);
1110 session = fm->session;
1111 GNUNET_assert(session != NULL);
1113 // test if message timed out
1114 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1117 GNUNET_assert(plugin->pending_fragment_messages > 0);
1118 plugin->pending_fragment_messages--;
1119 GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1120 plugin->pending_Fragment_Messages_tail, fm);
1122 GNUNET_free(fm->msg);
1125 check_fragment_queue(plugin);
1130 if (fm->message_size > WLAN_MTU)
1132 size += sizeof(struct FragmentationHeader);
1133 // check/set for retransmission
1134 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0)
1137 // be positive and try again later :-D
1138 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(
1140 // find first missing fragment
1142 fm->message_pos = 0;
1144 //test if ack 0 was already received
1147 //if fragment is present, take next
1148 if (akt->fragment_num == fm->message_pos)
1152 //next ack is bigger then the fragment number
1153 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1154 //and we send 3 again, the next number should be 4
1155 else if (akt->fragment_num > fm->message_pos)
1166 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1168 fragheader.fragment_off_or_num = htons(fm->message_pos);
1169 fragheader.message_id = htonl(session->message_id_out);
1171 // start should be smaller then the packet size
1172 GNUNET_assert(copyoffset < fm->message_size);
1173 copystart = fm->msg + copyoffset;
1175 //size of the fragment is either the MTU - overhead
1176 //or the missing part of the message in case this is the last fragment
1177 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1178 WLAN_MTU - sizeof(struct FragmentationHeader));
1179 fragheader.header.size = htons(copysize
1180 + sizeof(struct FragmentationHeader));
1181 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1183 //get the next missing fragment
1187 //test if ack was already received
1190 //if fragment is present, take next
1191 if (akt->fragment_num == fm->message_pos)
1195 //next ack is bigger then the fragment number
1196 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1197 //and we send 3 again, the next number should be 4
1198 else if (akt->fragment_num > fm->message_pos)
1208 // there is no need to split
1209 copystart = fm->msg;
1210 copysize = fm->message_size;
1214 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1215 + sizeof(struct GNUNET_MessageHeader);
1216 msgheader = GNUNET_malloc(size);
1217 msgheader->size = htons(size);
1218 msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1220 radioHeader = (struct RadiotapHeader*) &msgheader[1];
1221 getRadiotapHeader(radioHeader);
1223 ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1224 getWlanHeader(ieeewlanheader);
1226 //could be faster if content is just send and not copyed before
1227 //fragmentheader is needed
1228 if (fm->message_size > WLAN_MTU)
1230 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1231 memcpy(&ieeewlanheader[1], &fragheader,
1232 sizeof(struct FragmentationHeader));
1233 fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1234 memcpy(&fragheaderptr[1], copystart, copysize);
1238 memcpy(&ieeewlanheader[1], copystart, copysize);
1241 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1242 if (bytes == GNUNET_SYSERR){
1243 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1244 _("Error writing to wlan healper. errno == %d, ERROR: %s\n"), errno, strerror(errno) );
1247 GNUNET_assert(bytes != GNUNET_SYSERR);
1251 finish = GNUNET_malloc(sizeof( struct Finish_send));
1252 finish->plugin = plugin;
1253 finish->msgheader = (char * ) msgheader + bytes;
1254 finish->size = size - bytes;
1255 finish->msgstart = msgheader;
1257 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1259 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1260 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1261 &finish_sending, finish);
1266 GNUNET_assert(bytes == size);
1268 GNUNET_free(msgheader);
1269 check_next_fragment_timeout(plugin);
1272 //check if this was the last fragment of this message, if true then queue at the end of the list
1273 if (copysize + copyoffset >= fm->message_size)
1275 GNUNET_assert(copysize + copyoffset == fm->message_size);
1277 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1278 plugin->pending_Fragment_Messages_tail, fm);
1280 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1281 plugin->pending_Fragment_Messages_tail, fm);
1282 // if fragments have opimized timeouts
1283 //sort_fragment_into_queue(plugin,fm);
1292 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1294 struct Finish_send * finish;
1295 struct Plugin * plugin;
1299 plugin = finish->plugin;
1301 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1303 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, finish->msgheader, finish->size);
1304 GNUNET_assert(bytes != GNUNET_SYSERR);
1306 GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1307 if (bytes != finish->size)
1310 finish->plugin = plugin;
1311 finish->msgheader = finish->msgheader + bytes;
1312 finish->size = finish->size - bytes;
1313 plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1314 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1315 &finish_sending, finish);
1319 GNUNET_free(finish->msgstart);
1320 GNUNET_free(finish);
1321 check_next_fragment_timeout(plugin);
1327 getRadiotapHeader(struct RadiotapHeader * Header){
1332 getWlanHeader(struct IeeeHeader * Header){
1341 * @param msgbuf pointer tor the data
1342 * @param msgbuf_size size of the data
1344 * @return 32bit crc value
1348 getcrc32 (const char *msgbuf,
1349 size_t msgbuf_size){
1350 //TODO calc some crc
1357 * @param msgbuf pointer tor the data
1358 * @param msgbuf_size size of the data
1360 * @return 16bit crc value
1364 getcrc16 (const char *msgbuf,
1365 size_t msgbuf_size){
1366 //TODO calc some crc
1371 * Function that can be used by the transport service to transmit
1372 * a message using the plugin.
1374 * @param cls closure
1375 * @param target who should receive this message
1376 * @param priority how important is the message
1377 * @param msgbuf the message to transmit
1378 * @param msgbuf_size number of bytes in 'msgbuf'
1379 * @param timeout when should we time out
1380 * @param session which session must be used (or NULL for "any")
1381 * @param addr the address to use (can be NULL if the plugin
1382 * is "on its own" (i.e. re-use existing TCP connection))
1383 * @param addrlen length of the address in bytes
1384 * @param force_address GNUNET_YES if the plugin MUST use the given address,
1385 * otherwise the plugin may use other addresses or
1386 * existing connections (if available)
1387 * @param cont continuation to call once the message has
1388 * been transmitted (or if the transport is ready
1389 * for the next transmission call; or if the
1390 * peer disconnected...)
1391 * @param cont_cls closure for cont
1392 * @return number of bytes used (on the physical network, with overheads);
1393 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1394 * and does NOT mean that the message was not transmitted (DV)
1397 wlan_plugin_send (void *cls,
1398 const struct GNUNET_PeerIdentity * target,
1401 unsigned int priority,
1402 struct GNUNET_TIME_Relative timeout,
1403 struct Session *session,
1407 GNUNET_TRANSPORT_TransmitContinuation cont,
1410 struct Plugin * plugin = cls;
1411 struct PendingMessage * newmsg = NULL;
1412 struct WlanHeader * wlanheader = NULL;
1413 //check if msglen > 0
1414 GNUNET_assert(msgbuf_size > 0);
1416 //get session if needed
1417 if (session == NULL)
1419 if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1421 session = get_Session(plugin, addr);
1425 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1426 _("Wlan Address len %d is wrong\n"), addrlen);
1431 //TODO target "problem" not solved
1432 session->target = *target;
1435 //first queue session
1436 queue_Session(plugin, session);
1438 //queue message in session
1439 //test if there is no other message in the "queue"
1440 GNUNET_assert (session->pending_message == NULL);
1442 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1443 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1444 wlanheader = (struct WlanHeader *) newmsg->msg;
1445 //copy msg to buffer, not fragmented / segmented yet, but with message header
1446 wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1447 wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1448 memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1449 wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1450 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1451 newmsg->transmit_cont = cont;
1452 newmsg->transmit_cont_cls = cont_cls;
1453 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1454 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1456 session->pending_message = newmsg;
1458 check_fragment_queue(plugin);
1459 //FIXME not the correct size
1465 static struct FragmentMessage *
1466 get_fragment_message_from_session(struct Session * session)
1468 struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1471 if (fm->session == session)
1481 * Function that can be used to force the plugin to disconnect
1482 * from the given peer and cancel all previous transmissions
1483 * (and their continuation).
1485 * @param cls closure
1486 * @param target peer from which to disconnect
1489 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1491 struct Plugin *plugin = cls;
1492 struct Sessionqueue * queue = plugin->sessions;
1493 struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1494 struct PendingMessage * pm = NULL;
1495 struct FragmentMessage * fm;
1497 // just look at all the session for the needed one
1498 while (queue != NULL)
1500 // content is never NULL
1501 GNUNET_assert (queue->content != NULL);
1502 if (memcmp(target, &(queue->content->target),
1503 sizeof(struct GNUNET_PeerIdentity)) == 0)
1506 //is this session pending for send
1507 while (pendingsession != NULL)
1509 if (pendingsession->content == queue->content)
1511 plugin->pendingsessions --;
1512 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1513 plugin->pending_Sessions_tail, pendingsession);
1514 GNUNET_free(pendingsession);
1517 pendingsession = pendingsession->next;
1520 //is something of this session in the fragment queue?
1521 fm = get_fragment_message_from_session(queue->content);
1522 free_fragment_message(plugin,fm);
1524 //dispose all received fragments
1525 free_rec_frag_queue(queue->content);
1527 // remove PendingMessage
1528 pm = queue->content->pending_message;
1529 GNUNET_free(pm->msg);
1532 GNUNET_free(queue->content);
1533 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1535 plugin->session_count --;
1540 queue = queue->next;
1546 * Convert the transports address to a nice, human-readable
1549 * @param cls closure
1550 * @param type name of the transport that generated the address
1551 * @param addr one of the addresses of the host, NULL for the last address
1552 * the specific address format depends on the transport
1553 * @param addrlen length of the address
1554 * @param numeric should (IP) addresses be displayed in numeric form?
1555 * @param timeout after how long should we give up?
1556 * @param asc function to call on each string
1557 * @param asc_cls closure for asc
1560 wlan_plugin_address_pretty_printer (void *cls,
1565 struct GNUNET_TIME_Relative timeout,
1566 GNUNET_TRANSPORT_AddressStringCallback
1570 const unsigned char * input;
1572 GNUNET_assert(cls !=NULL);
1575 /* invalid address (MAC addresses have 6 bytes) */
1577 asc (asc_cls, NULL);
1580 input = (const unsigned char*) addr;
1581 GNUNET_snprintf (ret,
1583 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1585 input[0], input[1], input[2], input[3], input[4], input[5]);
1592 * Another peer has suggested an address for this
1593 * peer and transport plugin. Check that this could be a valid
1594 * address. If so, consider adding it to the list
1597 * @param cls closure
1598 * @param addr pointer to the address
1599 * @param addrlen length of addr
1600 * @return GNUNET_OK if this is a plausible address for this peer
1606 wlan_plugin_address_suggested (void *cls,
1610 //struct Plugin *plugin = cls;
1612 /* check if the address is plausible; if so,
1613 add it to our list! */
1615 GNUNET_assert(cls !=NULL);
1616 //FIXME mitm is not checked
1617 //Mac Adress has 6 bytes
1619 /* TODO check for bad addresses like milticast, broadcast, etc */
1622 return GNUNET_SYSERR;
1625 return GNUNET_SYSERR;
1630 * Function called for a quick conversion of the binary address to
1631 * a numeric address. Note that the caller must not free the
1632 * address and that the next call to this function is allowed
1633 * to override the address again.
1635 * @param cls closure
1636 * @param addr binary address
1637 * @param addrlen length of the address
1638 * @return string representing the same address
1641 wlan_plugin_address_to_string (void *cls,
1646 const unsigned char * input;
1648 GNUNET_assert(cls !=NULL);
1651 /* invalid address (MAC addresses have 6 bytes) */
1655 input = (const unsigned char*) addr;
1656 GNUNET_snprintf (ret,
1658 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1660 input[0], input[1], input[2], input[3], input[4], input[5]);
1661 return GNUNET_strdup (ret);
1665 * Function to test if fragment number already exists in the fragments received
1667 * @param session session the fragment belongs to
1668 * @param fh Fragmentheader of the fragment
1669 * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
1673 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1675 struct RecQueue * rec_queue = session->frag_head;
1676 while (rec_queue != NULL)
1678 if (rec_queue->num == fh->fragment_off_or_num)
1682 rec_queue = rec_queue->next;
1689 * Function to insert a fragment in a queue of a session
1690 * @param session session the fragment belongs to
1691 * @param rec_queue fragment to add
1695 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1697 struct RecQueue * rec_queue2 = session->frag_head;
1698 struct WlanHeader * wlanheader = NULL;
1699 //first received fragment of message
1700 if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1702 session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1704 //this is the first fragment of the message (fragment id 0)
1705 if (rec_queue->num == 0)
1707 wlanheader = (struct WlanHeader *) rec_queue->msg;
1708 session->rec_size = wlanheader->header.size;
1712 while (rec_queue2 != NULL)
1714 if (rec_queue2->num > rec_queue->num)
1716 //next element number is grater than the current num
1717 GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1720 rec_queue = rec_queue->next;
1722 //no element has a grater number
1723 GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1727 * Function to dispose the fragments received for a message
1728 * @param session session to free the fragments from
1732 free_rec_frag_queue(struct Session * session)
1734 struct RecQueue * rec_queue = session->frag_head;
1735 struct RecQueue * rec_queue2;
1736 while (rec_queue != NULL)
1738 rec_queue2 = rec_queue;
1739 rec_queue = rec_queue->next;
1740 GNUNET_free(rec_queue2);
1742 session->frag_head = NULL;
1743 session->frag_tail = NULL;
1744 session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1748 * Function to check if all fragments of a message have been received
1749 * @param plugin the plugin handle
1750 * @param session_light information of the message sender
1751 * @param session session the message belongs to
1755 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1756 struct RecQueue * rec_queue = session->frag_head;
1757 int packetsize = session->rec_size;
1761 //some fragment should be received
1762 GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1763 //check if first fragment is present
1764 if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1767 while (rec_queue != NULL){
1768 sum += rec_queue->size;
1769 //check if all fragment numbers are present
1770 if (rec_queue->num != aktnum){
1774 rec_queue = rec_queue->next;
1776 //sum should always be smaller or equal of
1777 GNUNET_assert(sum <= packetsize);
1778 if(sum == packetsize){
1781 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1782 "check_rec_finished_msg: A message with fragments is complete\n");
1785 //copy fragments together
1786 msg = GNUNET_malloc(packetsize);
1787 rec_queue = session->frag_head;
1789 while (rec_queue != NULL){
1790 memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1791 aktnum += rec_queue->size;
1792 rec_queue = rec_queue->next;
1794 free_rec_frag_queue(session);
1795 //call wlan_process_helper to process the message
1796 wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1803 * Function used for to process the data received from the wlan interface
1805 * @param cls the plugin handle
1806 * @param client client which send the data (not used)
1807 * @param hdr hdr of the GNUNET_MessageHeader
1810 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr)
1812 struct Plugin *plugin = cls;
1813 struct Session * session = NULL;
1814 struct Session_light * session_light = NULL;
1816 struct WlanHeader * wlanheader = NULL;
1817 struct FragmentationHeader * fh = NULL;
1818 struct FragmentMessage * fm = NULL;
1820 const char * tempmsg = NULL;
1822 struct AckQueue * ack = NULL;
1823 struct AckQueue * ack2 = NULL;
1825 struct RecQueue * rec_queue = NULL;
1826 const struct GNUNET_MessageHeader * temp_hdr = NULL;
1828 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1833 GNUNET_ERROR_TYPE_DEBUG,
1834 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %i\n",
1838 //TODO better DOS protection, error handling
1839 GNUNET_assert(client != NULL);
1840 session_light = (struct Session_light *) client;
1841 if (session_light->session == NULL)
1843 session_light->session = get_Session(plugin, session_light->addr);
1845 GNUNET_assert(GNUNET_HELLO_get_id(
1846 (const struct GNUNET_HELLO_Message *) &hdr[1],
1847 &(session_light->session->target) ) != GNUNET_SYSERR);
1852 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1856 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1857 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %i\n",
1861 GNUNET_assert(client != NULL);
1862 session_light = (struct Session_light *) client;
1863 if (session_light->session == NULL)
1865 session_light->session = search_session(plugin, session_light->addr);
1867 session = session_light->session;
1868 wlanheader = (struct WlanHeader *) hdr;
1869 tempmsg = (char*) &wlanheader[1];
1870 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
1872 if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc)
1874 //wrong crc, dispose message
1875 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN message crc was wrong\n");
1880 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1884 //if not in session list
1885 if (session == NULL)
1888 //try if it is a hello message
1889 if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
1892 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1893 "New WLAN Client\n");
1895 session = create_session(plugin, session_light->addr);
1896 session_light->session = session;
1897 GNUNET_assert(GNUNET_HELLO_get_id(
1898 (const struct GNUNET_HELLO_Message *) temp_hdr,
1899 &session->target ) != GNUNET_SYSERR);
1904 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1905 "WLAN client not in session list and not a hello message\n");
1911 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1915 //"receive" the message
1916 struct GNUNET_TRANSPORT_ATS_Information distance[2];
1917 distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1918 distance[0].value = htonl(1);
1919 distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1920 distance[1].value = htonl(0);
1922 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1923 "After Information\n");
1925 plugin->env->receive(plugin->env, &(session->target), temp_hdr,
1926 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1927 session, session->addr, sizeof(session->addr));
1929 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1935 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1940 GNUNET_ERROR_TYPE_DEBUG,
1941 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT size: %i\n",
1945 GNUNET_assert(client != NULL);
1946 session_light = (struct Session_light *) client;
1947 if (session_light->session == NULL)
1949 session_light->session = search_session(plugin, session_light->addr);
1951 session = session_light->session;
1953 fh = (struct FragmentationHeader *) hdr;
1954 tempmsg = (char*) &fh[1];
1956 //if not in session list
1957 if (session != NULL)
1959 if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1961 //wrong crc, dispose message
1962 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1963 "WLAN fragment crc was wrong\n");
1968 //todo fragments do not timeout
1969 //check if message_id is rigth or it is a new msg
1970 if ((session->message_id_in == ntohs(fh->message_id))
1971 || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1973 session->message_id_in = ntohs(fh->message_id);
1974 if (is_double_msg(session, fh) != GNUNET_YES)
1977 = GNUNET_malloc(sizeof (struct RecQueue) +
1978 ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1979 rec_queue->size = ntohs(fh->header.size
1980 - sizeof(struct FragmentationHeader));
1981 rec_queue->num = ntohs(fh->fragment_off_or_num);
1982 rec_queue->msg = (char*) &rec_queue[1];
1983 //copy msg to buffer
1984 memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1985 insert_fragment_in_queue(session, rec_queue);
1986 check_rec_finished_msg(plugin, session_light, session);
1990 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1991 "WLAN fragment is a clone\n");
1998 GNUNET_ERROR_TYPE_INFO,
1999 "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
2006 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2007 "WLAN client not in session list and it is a fragment message\n");
2013 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2018 GNUNET_ERROR_TYPE_DEBUG,
2019 "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %i\n",
2023 GNUNET_assert(client != NULL);
2024 session_light = (struct Session_light *) client;
2025 if (session_light->session == NULL)
2027 session_light->session = search_session(plugin, session_light->addr);
2028 GNUNET_assert(session_light->session != NULL);
2030 session = session_light->session;
2031 fh = (struct FragmentationHeader *) &hdr[1];
2032 if (fh->message_id == session->message_id_out)
2034 fm = get_fragment_message_from_session(session);
2039 while (ack2 != NULL)
2042 if (ack2->fragment_num != fh->fragment_off_or_num)
2044 // check if next ack has bigger number
2045 if (ack2->fragment_num > fh->fragment_off_or_num)
2047 ack = GNUNET_malloc(sizeof(struct AckQueue));
2048 ack->fragment_num = fh->fragment_off_or_num;
2049 GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
2051 check_finished_fragment(plugin, fm);
2062 //GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
2063 //should never happen but...
2064 //check_finished_fragment(plugin, fm);
2068 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2069 "WLAN fragment not in fragment list but id is right\n");
2079 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2080 "WLAN packet inside the WLAN helper packet has not the right type\n");
2085 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2086 "Helper finished\n");
2092 * Function used for to process the data from the suid process
2094 * @param cls the plugin handle
2095 * @param client which send the data (not used)
2096 * @param hdr of the GNUNET_MessageHeader
2100 wlan_process_helper (void *cls,
2102 const struct GNUNET_MessageHeader *hdr)
2104 struct Plugin *plugin = cls;
2105 struct IeeeHeader * wlanIeeeHeader = NULL;
2106 struct Session_light * session_light = NULL;
2107 const struct GNUNET_MessageHeader * temp_hdr = NULL;
2112 if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
2116 GNUNET_ERROR_TYPE_DEBUG,
2117 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %i\n",
2121 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2122 GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
2123 wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
2125 session_light = GNUNET_malloc(sizeof(struct Session_light));
2126 memcpy(session_light->addr, &(wlanIeeeHeader->mac3), sizeof(struct MacAddress));
2127 session_light->session = search_session(plugin, session_light->addr);
2129 //process only if it is an broadcast or for this computer both with the gnunet bssid
2131 if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress)))
2133 //check for broadcast or mac
2134 if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac, sizeof(struct MacAddress))
2135 || memcmp(&(wlanIeeeHeader->mac1), &(plugin->mac_address),
2136 sizeof(struct MacAddress)))
2138 // process the inner data
2140 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2141 while (pos < hdr->size)
2143 wlan_data_helper(plugin, session_light, temp_hdr);
2144 pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
2150 GNUNET_free(session_light);
2156 else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
2162 GNUNET_ERROR_TYPE_DEBUG,
2163 "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %i\n",
2168 //TODO use struct wlan_helper_control
2169 if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
2171 //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
2172 memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
2174 GNUNET_ERROR_TYPE_DEBUG,
2175 "Notifying transport of address %s\n",
2176 wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(hdr->size) - sizeof(struct GNUNET_MessageHeader)));
2177 plugin->env->notify_address(plugin->env->cls, "wlan",
2178 &plugin->mac_address, sizeof(struct MacAddress),
2179 GNUNET_TIME_UNIT_FOREVER_REL);
2183 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
2184 plugin->mac_address);
2193 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN helper packet has not the right type\n");
2199 * We have been notified that wlan-helper has written something to stdout.
2200 * Handle the output, then reschedule this function to be called again once
2201 * more is available.
2203 * @param cls the plugin handle
2204 * @param tc the scheduling context
2208 wlan_plugin_helper_read (void *cls,
2209 const struct GNUNET_SCHEDULER_TaskContext *tc)
2211 struct Plugin *plugin = cls;
2212 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2216 "Start reading from STDIN\n");
2219 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2222 char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2225 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
2226 mybuf, sizeof(mybuf));
2230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2231 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
2235 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
2236 mybuf, bytes, GNUNET_NO, GNUNET_NO);
2238 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2239 plugin->server_read_task =
2240 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
2241 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
2246 * Start the gnunet-wlan-helper process.
2248 * @param plugin the transport plugin
2249 * @param testmode should we use the dummy driver for testing?
2250 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2253 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2255 const char * filename = "gnunet-transport-wlan-helper";
2256 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2257 if (plugin->server_stdout == NULL)
2258 return GNUNET_SYSERR;
2260 plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2261 if (plugin->server_stdin == NULL)
2262 return GNUNET_SYSERR;
2265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2266 "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename, plugin->interface, testmode);
2268 /* Start the server process */
2271 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2272 plugin->server_stdout, filename,filename, plugin->interface, ((testmode==1)?"1":(testmode==2)?"2":"0"), NULL);
2273 if (plugin->server_proc == NULL)
2276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2277 "Failed to start gnunet-wlan-helper process\n");
2279 return GNUNET_SYSERR;
2282 /* Close the write end of the read pipe */
2283 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2285 /* Close the read end of the write pipe */
2286 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2288 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2289 GNUNET_DISK_PIPE_END_READ);
2290 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2291 GNUNET_DISK_PIPE_END_WRITE);
2293 GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2297 "Adding server_read_task for the wlan-helper\n");
2302 plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2303 GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2304 &wlan_plugin_helper_read, plugin);
2311 * Exit point from the plugin.
2316 libgnunet_plugin_transport_wlan_done (void *cls)
2318 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2319 struct Plugin *plugin = api->cls;
2322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2323 "libgnunet_plugin_transport_wlan_done started\n");
2326 GNUNET_assert(cls !=NULL);
2328 if (plugin->consoltoken != NULL)
2329 GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2331 GNUNET_free_non_null(plugin->interface);
2332 GNUNET_free (plugin);
2338 * Entry point for the plugin.
2340 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2341 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2344 libgnunet_plugin_transport_wlan_init (void *cls)
2346 //struct GNUNET_SERVICE_Context *service;
2347 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2348 struct GNUNET_TRANSPORT_PluginFunctions *api;
2349 struct Plugin *plugin;
2350 static unsigned long long testmode =0;
2352 GNUNET_assert(cls !=NULL);
2354 plugin = GNUNET_malloc (sizeof (struct Plugin));
2356 plugin->pendingsessions = 0;
2357 plugin->session_count = 0;
2358 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2359 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2360 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2363 if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2365 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg, "transport-wlan",
2366 "TESTMODE", &testmode))
2370 if (GNUNET_CONFIGURATION_have_value(env->cfg,
2371 "transport-wlan", "INTERFACE"))
2373 if (GNUNET_CONFIGURATION_get_value_string (env->cfg,
2374 "transport-wlan","INTERFACE", &(plugin->interface)) != GNUNET_YES){
2375 libgnunet_plugin_transport_wlan_done(plugin);
2380 wlan_transport_start_wlan_helper(plugin, testmode);
2381 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2383 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2384 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2386 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2388 api->send = &wlan_plugin_send;
2389 api->disconnect = &wlan_plugin_disconnect;
2390 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2391 api->check_address = &wlan_plugin_address_suggested;
2392 api->address_to_string = &wlan_plugin_address_to_string;
2395 start_next_message_id();
2398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2399 "wlan init finished\n");
2405 /* end of plugin_transport_wlan.c */