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_NO
55 * After how long do we expire an address that we
56 * learned from another peer if it is not reconfirmed
59 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
62 * Initial handshake message for a session.
67 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
69 struct GNUNET_MessageHeader header;
72 * Identity of the node connecting (TCP client)
74 struct GNUNET_PeerIdentity clientIdentity;
79 * Encapsulation of all of the state of the plugin.
86 struct GNUNET_TRANSPORT_PluginEnvironment *env;
89 * List of open sessions. head
91 struct Sessionqueue *sessions;
94 * List of open sessions. tail
96 struct Sessionqueue *sessions_tail;
99 * encapsulation to the local wlan server prog
102 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
106 * stdout pipe handle for the gnunet-wlan-helper process
108 struct GNUNET_DISK_PipeHandle *server_stdout;
111 * stdout file handle for the gnunet-wlan-helper process
113 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
116 * stdin pipe handle for the gnunet-wlan-helper process
118 struct GNUNET_DISK_PipeHandle *server_stdin;
121 * stdin file handle for the gnunet-wlan-helper process
123 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
126 * ID of select gnunet-nat-server std read task
128 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
131 * ID of select gnunet-nat-server std read task
133 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
136 * The process id of the server process (if behind NAT)
138 struct GNUNET_OS_Process *server_proc;
141 * The interface of the wlan card given to us by the user.
146 * The mac_address of the wlan card given to us by the helper.
151 * Sessions currently pending for transmission
152 * to this peer, if any.
154 struct Sessionqueue * pending_Sessions;
157 * Sessions currently pending for transmission
158 * to this peer (tail), if any.
160 struct Sessionqueue * pending_Sessions_tail;
163 * number of pending sessions
165 unsigned int pendingsessions;
168 * Messages in the fragmentation queue, head
171 struct FragmentMessage * pending_Fragment_Messages_head;
174 * Messages in the fragmentation queue, tail
177 struct FragmentMessage * pending_Fragment_Messages_tail;
180 * number of pending fragment message
183 unsigned int pending_fragment_messages;
191 struct Sessionqueue * next;
192 struct Sessionqueue * prev;
193 struct Session * content;
200 struct AckQueue * next;
201 struct AckQueue * prev;
206 * Information kept for each message that is yet to
209 struct PendingMessage
213 * The pending message
218 * Continuation function to call once the message
219 * has been sent. Can be NULL if there is no
220 * continuation to call.
222 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
225 * Cls for transmit_cont
227 void * transmit_cont_cls;
230 * Timeout value for the pending message.
232 struct GNUNET_TIME_Absolute timeout;
235 * Size of the message
242 * Session handle for connections.
250 struct SessionHeader header;
253 * Pointer to the global plugin struct.
255 struct Plugin *plugin;
258 * Message currently pending for transmission
259 * to this peer, if any.
261 struct PendingMessage *pending_message;
264 * To whom are we talking to (set to our identity
265 * if we are still waiting for the welcome message)
267 struct GNUNET_PeerIdentity target;
270 * encapsulation of the data
272 //struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
280 * Address of the other peer (either based on our 'connect'
281 * call or on our 'accept' call).
286 * Last activity on this connection. Used to select preferred
289 struct GNUNET_TIME_Absolute last_activity;
292 * current number for message incoming, to distinguish between the messages
294 uint32_t message_id_in;
297 * current number for message outgoing, to distinguish between the messages
299 uint32_t message_id_out;
302 * does this session have a message in the fragment queue
312 struct FragmentMessage
315 * Session this message belongs to
318 struct Session *session;
321 * This is a doubly-linked list.
323 struct FragmentMessage *next;
326 * This is a doubly-linked list.
328 struct FragmentMessage *prev;
331 * The pending message
336 * Timeout value for the pending message.
338 struct GNUNET_TIME_Absolute timeout;
341 * Timeout value for the pending fragments.
342 * Stores the time when the next msg fragment ack has to be received
344 struct GNUNET_TIME_Absolute next_ack;
347 * Sorted queue with the acks received for fragments; head
350 struct AckQueue * head;
353 * Sorted queue with the acks received for fragments; tail
356 struct AckQueue * tail;
359 * Size of the message
364 * pos / next fragment number in the message, for fragmentation/segmentation,
365 * some acks can be missing but there is still time
367 uint32_t message_pos;
372 * Header for messages which need fragmentation
377 struct GNUNET_MessageHeader header;
380 * checksum/error correction
382 uint32_t crc GNUNET_PACKED;
385 * To whom are we talking to (set to our identity
386 * if we are still waiting for the welcome message)
388 struct GNUNET_PeerIdentity target;
390 // followed by payload
395 * Header for messages which need fragmentation
397 struct FragmentationHeader
400 struct GNUNET_MessageHeader header;
403 * To whom are we talking to (set to our identity
404 * if we are still waiting for the welcome message)
406 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
409 * ID of message, to distinguish between the messages, picked randomly.
411 uint32_t message_id GNUNET_PACKED;
414 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
416 uint16_t fragment_off_or_num GNUNET_PACKED;
419 * CRC of fragment (for error checking)
421 uint16_t message_crc GNUNET_PACKED;
425 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
426 * // 0x2 has data (not only ack)
427 * // 0x4 last fragment of message
430 // uint32_t flags GNUNET_PACKED;
433 * checksum/error correction
435 // uint32_t crc GNUNET_PACKED;
437 // followed by payload unless ACK
441 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
443 int getRadiotapHeader (struct RadiotapHeader * Header);
444 int getWlanHeader (struct IeeeHeader * Header);
445 static int wlan_plugin_address_suggested (void *cls,
448 uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
449 static void do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
450 static void check_fragment_queue (struct Plugin * plugin);
453 * get the next message number, at the moment just a random one
458 get_next_message_id()
460 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
464 * start next message number generator
468 start_next_message_id()
470 //GNUNET_CRYPTO_random_init;
475 * get Session from address
479 //TODO add other possibilities to find the right session (are there other?)
480 static struct Session *
481 get_Session (struct Plugin *plugin,
484 struct Sessionqueue * queue = plugin->sessions;
485 struct Sessionqueue * lastitem = NULL;
488 //just look at all the session for the needed one
489 while (queue != NULL){
490 // content is never NULL
491 GNUNET_assert (queue->content == NULL);
492 char * addr2 = queue->content->addr;
493 if (memcmp(addr, addr2, 6) == 0)
496 return queue->content;
503 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
505 GNUNET_CONTAINER_DLL_insert(plugin->sessions, plugin->sessions_tail, queue);
507 queue->content = GNUNET_malloc (sizeof (struct Session));
508 queue->content->plugin = plugin;
509 memcpy(queue->content->addr, addr, 6);
510 queue->content->message_id_out = get_next_message_id();
511 queue->content->has_fragment = 0;
513 //queue welcome message for new sessions, not realy needed
514 //struct WelcomeMessage welcome;
515 struct PendingMessage *pm;
516 pm = GNUNET_malloc (sizeof (struct PendingMessage));
517 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
518 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
519 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
520 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
521 //welcome.clientIdentity = *plugin->env->my_identity;
522 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
523 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
524 queue->content->pending_message = pm;
525 plugin->pendingsessions ++;
526 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
528 check_fragment_queue(plugin);
530 return queue->content;
535 * Queue the session to send data
539 queue_Session (struct Plugin *plugin,
540 struct Session * session)
542 struct Sessionqueue * queue = plugin->pending_Sessions;
543 struct Sessionqueue * lastitem = NULL;
545 while (queue != NULL){
546 // content is never NULL
547 GNUNET_assert (queue->content == NULL);
548 // is session already in queue?
549 if (session == queue->content){
557 // Session is not in the queue
559 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
560 queue->content = session;
563 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
564 plugin->pending_Sessions_tail,
565 plugin->pending_Sessions_tail, queue);
566 plugin->pendingsessions ++;
572 free_acks (struct FragmentMessage * pm){
573 struct AckQueue * fq;
574 while (pm->head != NULL){
576 GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq);
583 delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc){
584 struct Plugin * plugin = cls;
585 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
587 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
590 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
591 plugin->server_write_task
592 = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
593 plugin->server_stdin_handle,
600 struct GNUNET_TIME_Relative
601 get_next_frag_timeout (struct FragmentMessage * fm)
603 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
608 * Function to get the timeout value for acks for this session
611 struct GNUNET_TIME_Relative
612 get_ack_timeout (struct FragmentMessage * fm){
613 return FRAGMENT_TIMEOUT;
618 * Function to set the timer for the next timeout of the fragment queue
621 check_next_fragment_timeout (struct Plugin * plugin){
622 struct FragmentMessage * fm;
623 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK){
624 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
626 fm = plugin->pending_Fragment_Messages_head;
628 plugin->server_write_task = GNUNET_SCHEDULER_add_delayed(get_next_frag_timeout(fm), &delay_fragment_task, plugin);
634 * Function to get the next queued Session, removes the session from the queue
637 static struct Session *
638 get_next_queue_Session (struct Plugin * plugin){
639 struct Session * session;
640 struct Sessionqueue * sessionqueue;
641 struct Sessionqueue * sessionqueue_alt;
642 struct PendingMessage * pm;
643 sessionqueue = plugin->pending_Sessions;
644 while (sessionqueue != NULL){
645 session = sessionqueue->content;
646 pm = session->pending_message;
648 //check for message timeout
649 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
650 //check if session has no message in the fragment queue
651 if (! session->has_fragment){
652 plugin->pendingsessions --;
653 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
654 plugin->pending_Sessions_tail, sessionqueue);
655 GNUNET_free(sessionqueue);
659 sessionqueue = sessionqueue->next;
663 session->pending_message = NULL;
664 //call the cont func that it did not work
665 if (pm->transmit_cont != NULL)
666 pm->transmit_cont (pm->transmit_cont_cls,
667 &(session->target), GNUNET_SYSERR);
668 GNUNET_free(pm->msg);
671 sessionqueue_alt = sessionqueue;
672 sessionqueue = sessionqueue->next;
673 plugin->pendingsessions --;
674 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
675 plugin->pending_Sessions_tail, sessionqueue_alt);
677 GNUNET_free(sessionqueue_alt);
688 * Function to sort the message into the message fragment queue
691 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
692 struct FragmentMessage * fm2;
693 //sort into the list at the right position
695 fm2 = plugin->pending_Fragment_Messages_head;
698 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
705 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
706 plugin->pending_Fragment_Messages_tail,fm2,fm);
711 * Function to check if there is some space in the fragment queue
715 check_fragment_queue (struct Plugin * plugin){
716 struct Session * session;
717 struct FragmentMessage * fm;
719 struct PendingMessage * pm;
721 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
722 session = get_next_queue_Session(plugin);
723 if (session != NULL){
724 pm = session->pending_message;
725 session->pending_message = NULL;
726 session->has_fragment = 1;
727 GNUNET_assert(pm != NULL);
729 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
730 fm->message_size = pm->message_size;
732 fm->session = session;
733 fm->timeout.abs_value = pm->timeout.abs_value;
735 fm->next_ack = GNUNET_TIME_absolute_get();
737 if (pm->transmit_cont != NULL)
738 pm->transmit_cont (pm->transmit_cont_cls,
739 &(session->target), GNUNET_OK);
742 sort_fragment_into_queue(plugin,fm);
743 plugin->pending_fragment_messages ++;
745 //generate new message id
746 session->message_id_out = get_next_message_id();
748 //check if timeout changed
749 check_next_fragment_timeout(plugin);
755 * Function called to when wlan helper is ready to get some data
758 * @param GNUNET_SCHEDULER_TaskContext
762 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
765 struct Plugin * plugin = cls;
766 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
770 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
773 struct Session * session;
774 struct FragmentMessage * fm;
775 struct IeeeHeader * wlanheader;
776 struct RadiotapHeader * radioHeader;
777 struct GNUNET_MessageHeader * msgheader;
778 struct FragmentationHeader fragheader;
780 const char * copystart = NULL;
781 uint16_t copysize = 0;
783 struct AckQueue * akt = NULL;
786 fm = plugin->pending_Fragment_Messages_head;
787 GNUNET_assert(fm != NULL);
788 session = fm->session;
789 GNUNET_assert(session != NULL);
791 // test if message timed out
792 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
794 GNUNET_assert(plugin->pending_fragment_messages > 0);
795 plugin->pending_fragment_messages --;
796 GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
797 plugin->pending_Fragment_Messages_tail, fm);
799 GNUNET_free(fm->msg);
802 check_fragment_queue(plugin);
805 if (fm->message_size > WLAN_MTU) {
806 size += sizeof(struct FragmentationHeader);
807 // check/set for retransmission
808 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
810 // be positive and try again later :-D
811 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
812 // find first missing fragment
816 //test if ack 0 was already received
818 //if fragment is present, take next
819 if (akt->fragment_num == fm->message_pos) {
822 //next ack is bigger then the fragment number
823 //in case there is something like this: (acks) 1, 2, 5, 6, ...
824 //and we send 3 again, the next number should be 4
825 else if (akt->fragment_num > fm->message_pos) {
836 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
837 fragheader.fragment_off_or_num = htons(fm->message_pos);
838 fragheader.message_id = htonl(session->message_id_out);
840 // start should be smaller then the packet size
841 GNUNET_assert(copyoffset < fm->message_size);
842 copystart = fm->msg + copyoffset;
844 //size of the fragment is either the MTU - overhead
845 //or the missing part of the message in case this is the last fragment
846 copysize = GNUNET_MIN(fm->message_size - copyoffset,
847 WLAN_MTU - sizeof(struct FragmentationHeader));
848 fragheader.header.size = htons(copysize);
849 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
852 //get the next missing fragment
856 //test if ack was already received
858 //if fragment is present, take next
859 if (akt->fragment_num == fm->message_pos) {
862 //next ack is bigger then the fragment number
863 //in case there is something like this: (acks) 1, 2, 5, 6, ...
864 //and we send 3 again, the next number should be 4
865 else if (akt->fragment_num > fm->message_pos) {
872 // there is no need to split
874 copysize = fm->message_size;
878 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
879 + sizeof(struct GNUNET_MessageHeader);
880 msgheader = GNUNET_malloc(size);
881 msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
882 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
884 radioHeader = (struct RadiotapHeader*) &msgheader[1];
885 getRadiotapHeader(radioHeader);
887 wlanheader = (struct IeeeHeader *) &radioHeader[1];
888 getWlanHeader(wlanheader);
891 //could be faster if content is just send and not copyed before
892 //fragmentheader is needed
893 if (fm->message_size > WLAN_MTU){
894 fragheader.message_crc = htons(getcrc16(copystart, copysize));
895 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
896 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
898 memcpy(&wlanheader[1],copystart,copysize);
901 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
902 GNUNET_assert(bytes == size);
904 //check if this was the last fragment of this message, if true then queue at the end of the list
905 if (copysize + copyoffset >= fm->message_size){
906 GNUNET_assert(copysize + copyoffset == fm->message_size);
908 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
909 plugin->pending_Fragment_Messages_tail, fm);
911 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
912 plugin->pending_Fragment_Messages_tail, fm);
913 // if fragments have opimized timeouts
914 //sort_fragment_into_queue(plugin,fm);
917 check_next_fragment_timeout(plugin);
926 * @param msgbuf pointer tor the data
927 * @param msgbuf_size size of the data
929 * @return 32bit crc value
933 getcrc32 (const char *msgbuf,
942 * @param msgbuf pointer tor the data
943 * @param msgbuf_size size of the data
945 * @return 16bit crc value
949 getcrc16 (const char *msgbuf,
956 * Function that can be used by the transport service to transmit
957 * a message using the plugin.
960 * @param target who should receive this message
961 * @param priority how important is the message
962 * @param msgbuf the message to transmit
963 * @param msgbuf_size number of bytes in 'msgbuf'
964 * @param timeout when should we time out
965 * @param session which session must be used (or NULL for "any")
966 * @param addr the address to use (can be NULL if the plugin
967 * is "on its own" (i.e. re-use existing TCP connection))
968 * @param addrlen length of the address in bytes
969 * @param force_address GNUNET_YES if the plugin MUST use the given address,
970 * otherwise the plugin may use other addresses or
971 * existing connections (if available)
972 * @param cont continuation to call once the message has
973 * been transmitted (or if the transport is ready
974 * for the next transmission call; or if the
975 * peer disconnected...)
976 * @param cont_cls closure for cont
977 * @return number of bytes used (on the physical network, with overheads);
978 * -1 on hard errors (i.e. address invalid); 0 is a legal value
979 * and does NOT mean that the message was not transmitted (DV)
982 wlan_plugin_send (void *cls,
983 const struct GNUNET_PeerIdentity * target,
986 unsigned int priority,
987 struct GNUNET_TIME_Relative timeout,
988 struct Session *session,
992 GNUNET_TRANSPORT_TransmitContinuation cont,
995 struct Plugin * plugin = cls;
996 struct PendingMessage * newmsg = NULL;
997 struct WlanHeader * wlanheader = NULL;
998 //check if msglen > 0
999 GNUNET_assert(msgbuf_size > 0);
1001 //get session if needed
1002 if (session == NULL) {
1003 if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
1004 session = get_Session(plugin, addr);
1006 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1007 _("Wlan Address len %d is wrong\n"),
1013 //TODO target "problem" not solved
1014 session->target = *target;
1017 //first queue session
1018 queue_Session(plugin, session);
1020 //queue message in session
1021 if (session->pending_message == NULL){
1022 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1023 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1024 wlanheader = (struct WlanHeader *) newmsg->msg;
1025 //copy msg to buffer, not fragmented / segmented yet, but with message header
1026 wlanheader->header.size = htons(msgbuf_size);
1027 wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
1028 wlanheader->target = *target;
1029 wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
1030 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1031 newmsg->transmit_cont = cont;
1032 newmsg->transmit_cont_cls = cont_cls;
1033 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1034 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1036 //TODO if message is send while hello is still pending, other cases should not occur
1038 check_fragment_queue(plugin);
1039 //FIXME not the correct size
1047 * Function that can be used to force the plugin to disconnect
1048 * from the given peer and cancel all previous transmissions
1049 * (and their continuation).
1051 * @param cls closure
1052 * @param target peer from which to disconnect
1055 wlan_plugin_disconnect (void *cls,
1056 const struct GNUNET_PeerIdentity *target)
1058 struct Plugin *plugin = cls;
1059 struct Sessionqueue * queue = plugin->sessions;
1060 struct Sessionqueue * lastitem = NULL;
1061 struct PendingMessage * pm;
1063 // just look at all the session for the needed one
1064 while (queue != NULL){
1065 // content is never NULL
1066 GNUNET_assert (queue->content == NULL);
1067 if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0)
1070 // remove PendingMessage
1071 pm = queue->content->pending_message;
1072 GNUNET_free(pm->msg);
1075 GNUNET_free(queue->content);
1076 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1083 queue = queue->next;
1089 * Convert the transports address to a nice, human-readable
1092 * @param cls closure
1093 * @param type name of the transport that generated the address
1094 * @param addr one of the addresses of the host, NULL for the last address
1095 * the specific address format depends on the transport
1096 * @param addrlen length of the address
1097 * @param numeric should (IP) addresses be displayed in numeric form?
1098 * @param timeout after how long should we give up?
1099 * @param asc function to call on each string
1100 * @param asc_cls closure for asc
1103 wlan_plugin_address_pretty_printer (void *cls,
1108 struct GNUNET_TIME_Relative timeout,
1109 GNUNET_TRANSPORT_AddressStringCallback
1113 const unsigned char * input;
1115 GNUNET_assert(cls !=NULL);
1118 /* invalid address (MAC addresses have 6 bytes) */
1120 asc (asc_cls, NULL);
1123 input = (const unsigned char*) addr;
1124 GNUNET_snprintf (ret,
1126 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1128 input[0], input[1], input[2], input[3], input[4], input[5]);
1135 * Another peer has suggested an address for this
1136 * peer and transport plugin. Check that this could be a valid
1137 * address. If so, consider adding it to the list
1140 * @param cls closure
1141 * @param addr pointer to the address
1142 * @param addrlen length of addr
1143 * @return GNUNET_OK if this is a plausible address for this peer
1149 wlan_plugin_address_suggested (void *cls,
1153 //struct Plugin *plugin = cls;
1155 /* check if the address is plausible; if so,
1156 add it to our list! */
1158 GNUNET_assert(cls !=NULL);
1159 //FIXME mitm is not checked
1160 //Mac Adress has 6 bytes
1162 /* TODO check for bad addresses like milticast, broadcast, etc */
1165 return GNUNET_SYSERR;
1168 return GNUNET_SYSERR;
1173 * Function called for a quick conversion of the binary address to
1174 * a numeric address. Note that the caller must not free the
1175 * address and that the next call to this function is allowed
1176 * to override the address again.
1178 * @param cls closure
1179 * @param addr binary address
1180 * @param addrlen length of the address
1181 * @return string representing the same address
1184 wlan_plugin_address_to_string (void *cls,
1189 const unsigned char * input;
1191 GNUNET_assert(cls !=NULL);
1194 /* invalid address (MAC addresses have 6 bytes) */
1198 input = (const unsigned char*) addr;
1199 GNUNET_snprintf (ret,
1201 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1203 input[0], input[1], input[2], input[3], input[4], input[5]);
1204 return GNUNET_strdup (ret);
1210 * Function used for to process the data from the suid process
1215 wlan_process_helper (void *cls,
1217 const struct GNUNET_MessageHeader *hdr)
1219 struct Plugin *plugin = cls;
1220 if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
1222 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
1224 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
1226 if (hdr->size == 6){
1227 plugin->mac_address = GNUNET_malloc(6);
1228 memcpy(plugin->mac_address, &hdr[1],6);
1229 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1230 plugin->env->notify_address (plugin->env->cls,
1232 &plugin->mac_address, sizeof(plugin->mac_address),
1233 GNUNET_TIME_UNIT_FOREVER_REL);
1235 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
1246 wlan_plugin_helper_read (void *cls,
1247 const struct GNUNET_SCHEDULER_TaskContext *tc)
1249 struct Plugin *plugin = cls;
1250 char mybuf[WLAN_MTU];
1253 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1255 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1256 mybuf, sizeof(mybuf));
1260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1261 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1265 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1266 mybuf, bytes, 0, GNUNET_NO);
1272 * Start the gnunet-wlan-helper process.
1274 * @param plugin the transport plugin
1276 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1279 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1282 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1283 if (plugin->server_stdout == NULL)
1284 return GNUNET_SYSERR;
1286 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1287 if (plugin->server_stdin == NULL)
1288 return GNUNET_SYSERR;
1291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1292 "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1294 /* Start the server process */
1295 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
1296 if (plugin->server_proc == NULL)
1299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1300 "Failed to start gnunet-wlan-helper process\n");
1302 return GNUNET_SYSERR;
1304 /* Close the write end of the read pipe */
1305 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1307 /* Close the read end of the write pipe */
1308 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1310 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1311 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
1313 plugin->server_read_task =
1314 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1315 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1322 * Entry point for the plugin.
1324 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1325 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1328 libgnunet_plugin_transport_wlan_init (void *cls)
1330 struct GNUNET_SERVICE_Context *service;
1331 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1332 struct GNUNET_TRANSPORT_PluginFunctions *api;
1333 struct Plugin *plugin;
1335 GNUNET_assert(cls !=NULL);
1337 service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
1338 if (service == NULL){
1339 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1340 _("Failed to start service for `%s' transport plugin.\n"),
1345 plugin = GNUNET_malloc (sizeof (struct Plugin));
1347 plugin->pendingsessions = 0;
1348 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1349 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1351 wlan_transport_start_wlan_helper(plugin);
1352 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1354 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1355 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1357 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1359 api->send = &wlan_plugin_send;
1360 api->disconnect = &wlan_plugin_disconnect;
1361 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1362 api->check_address = &wlan_plugin_address_suggested;
1363 api->address_to_string = &wlan_plugin_address_to_string;
1366 start_next_message_id();
1373 * Exit point from the plugin.
1377 libgnunet_plugin_transport_wlan_done (void *cls)
1379 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1380 struct Plugin *plugin = api->cls;
1382 GNUNET_assert(cls !=NULL);
1384 GNUNET_free_non_null(plugin->mac_address);
1385 GNUNET_free (plugin);
1390 /* end of plugin_transport_wlan.c */