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
49 #define FRAGMENT_TIMEOUT 1000
51 #define FRAGMENT_QUEUE_SIZE 10
53 #define DEBUG_wlan GNUNET_NO
56 * After how long do we expire an address that we
57 * learned from another peer if it is not reconfirmed
60 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
63 * Initial handshake message for a session.
68 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
70 struct GNUNET_MessageHeader header;
73 * Identity of the node connecting (TCP client)
75 struct GNUNET_PeerIdentity clientIdentity;
80 * Encapsulation of all of the state of the plugin.
87 struct GNUNET_TRANSPORT_PluginEnvironment *env;
90 * List of open sessions. head
92 struct Sessionqueue *sessions;
95 * List of open sessions. tail
97 struct Sessionqueue *sessions_tail;
100 * encapsulation to the local wlan server prog
103 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
107 * stdout pipe handle for the gnunet-wlan-helper process
109 struct GNUNET_DISK_PipeHandle *server_stdout;
112 * stdout file handle for the gnunet-wlan-helper process
114 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
117 * stdin pipe handle for the gnunet-wlan-helper process
119 struct GNUNET_DISK_PipeHandle *server_stdin;
122 * stdin file handle for the gnunet-wlan-helper process
124 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
127 * ID of select gnunet-nat-server std read task
129 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
132 * ID of select gnunet-nat-server std read task
134 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
137 * The process id of the server process (if behind NAT)
139 struct GNUNET_OS_Process *server_proc;
142 * The interface of the wlan card given to us by the user.
147 * The mac_address of the wlan card given to us by the helper.
152 * Sessions currently pending for transmission
153 * to this peer, if any.
155 struct Sessionqueue * pending_Sessions;
158 * Sessions currently pending for transmission
159 * to this peer (tail), if any.
161 struct Sessionqueue * pending_Sessions_tail;
164 * number of pending sessions
166 uint pendingsessions;
169 * Messages in the fragmentation queue, head
172 struct FragmentMessage * pending_Fragment_Messages_head;
175 * Messages in the fragmentation queue, tail
178 struct FragmentMessage * pending_Fragment_Messages_tail;
181 * number of pending fragment message
184 uint pending_fragment_messages;
192 struct Sessionqueue * next;
193 struct Sessionqueue * prev;
194 struct Session * content;
201 struct AckQueue * next;
202 struct AckQueue * prev;
207 * Information kept for each message that is yet to
210 struct PendingMessage
214 * The pending message
219 * Continuation function to call once the message
220 * has been sent. Can be NULL if there is no
221 * continuation to call.
223 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
226 * Cls for transmit_cont
228 void * transmit_cont_cls;
231 * Timeout value for the pending message.
233 struct GNUNET_TIME_Absolute timeout;
236 * Size of the message
243 * Session handle for connections.
251 struct SessionHeader header;
254 * Pointer to the global plugin struct.
256 struct Plugin *plugin;
259 * Message currently pending for transmission
260 * to this peer, if any.
262 struct PendingMessage *pending_message;
265 * To whom are we talking to (set to our identity
266 * if we are still waiting for the welcome message)
268 struct GNUNET_PeerIdentity target;
271 * encapsulation of the data
273 //struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
281 * Address of the other peer (either based on our 'connect'
282 * call or on our 'accept' call).
287 * Last activity on this connection. Used to select preferred
290 struct GNUNET_TIME_Absolute last_activity;
293 * current number for message incoming, to distinguish between the messages
295 uint32_t message_id_in;
298 * current number for message outgoing, to distinguish between the messages
300 uint32_t message_id_out;
303 * does this session have a message in the fragment queue
313 struct FragmentMessage
316 * Session this message belongs to
319 struct Session *session;
322 * This is a doubly-linked list.
324 struct FragmentMessage *next;
327 * This is a doubly-linked list.
329 struct FragmentMessage *prev;
332 * The pending message
337 * Timeout value for the pending message.
339 struct GNUNET_TIME_Absolute timeout;
342 * Timeout value for the pending fragments.
343 * Stores the time when the next msg fragment ack has to be received
345 struct GNUNET_TIME_Absolute next_ack;
348 * Sorted queue with the acks received for fragments; head
351 struct AckQueue * head;
354 * Sorted queue with the acks received for fragments; tail
357 struct AckQueue * tail;
360 * Size of the message
365 * pos / next fragment number in the message, for fragmentation/segmentation,
366 * some acks can be missing but there is still time
368 uint32_t message_pos;
373 * Header for messages which need fragmentation
378 struct GNUNET_MessageHeader header;
381 * checksum/error correction
383 uint32_t crc GNUNET_PACKED;
386 * To whom are we talking to (set to our identity
387 * if we are still waiting for the welcome message)
389 struct GNUNET_PeerIdentity target;
391 // followed by payload
396 * Header for messages which need fragmentation
398 struct FragmentationHeader
401 struct GNUNET_MessageHeader header;
404 * To whom are we talking to (set to our identity
405 * if we are still waiting for the welcome message)
407 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
410 * ID of message, to distinguish between the messages, picked randomly.
412 uint32_t message_id GNUNET_PACKED;
415 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
417 uint16_t fragment_off_or_num GNUNET_PACKED;
420 * CRC of fragment (for error checking)
422 uint16_t message_crc GNUNET_PACKED;
426 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
427 * // 0x2 has data (not only ack)
428 * // 0x4 last fragment of message
431 // uint32_t flags GNUNET_PACKED;
434 * checksum/error correction
436 // uint32_t crc GNUNET_PACKED;
438 // followed by payload unless ACK
442 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
444 int getRadiotapHeader (struct RadiotapHeader * Header);
445 int getWlanHeader (struct IeeeHeader * Header);
446 static int wlan_plugin_address_suggested (void *cls,
449 uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
450 static void do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
451 static void check_fragment_queue (struct Plugin * plugin);
454 * get the next message number, at the moment just a random one
459 get_next_message_id()
461 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
465 * start next message number generator
469 start_next_message_id()
471 //GNUNET_CRYPTO_random_init;
476 * get Session from address
480 //TODO add other possibilities to find the right session (are there other?)
481 static struct Session *
482 get_Session (struct Plugin *plugin,
485 struct Sessionqueue * queue = plugin->sessions;
486 struct Sessionqueue * lastitem = NULL;
489 //just look at all the session for the needed one
490 while (queue != NULL){
491 // content is never NULL
492 GNUNET_assert (queue->content == NULL);
493 char * addr2 = queue->content->addr;
494 if (memcmp(addr, addr2, 6) == 0)
497 return queue->content;
504 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
506 GNUNET_CONTAINER_DLL_insert(plugin->sessions, plugin->sessions_tail, queue);
508 queue->content = GNUNET_malloc (sizeof (struct Session));
509 queue->content->plugin = plugin;
510 memcpy(queue->content->addr, addr, 6);
511 queue->content->message_id_out = get_next_message_id();
512 queue->content->has_fragment = 0;
514 //queue welcome message for new sessions, not realy needed
515 //struct WelcomeMessage welcome;
516 struct PendingMessage *pm;
517 pm = GNUNET_malloc (sizeof (struct PendingMessage));
518 pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
519 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
520 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
521 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
522 //welcome.clientIdentity = *plugin->env->my_identity;
523 memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
524 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
525 queue->content->pending_message = pm;
526 plugin->pendingsessions ++;
527 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
529 check_fragment_queue(plugin);
531 return queue->content;
536 * Queue the session to send data
540 queue_Session (struct Plugin *plugin,
541 struct Session * session)
543 struct Sessionqueue * queue = plugin->pending_Sessions;
544 struct Sessionqueue * lastitem = NULL;
546 while (queue != NULL){
547 // content is never NULL
548 GNUNET_assert (queue->content == NULL);
549 // is session already in queue?
550 if (session == queue->content){
558 // Session is not in the queue
560 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
561 queue->content = session;
564 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
565 plugin->pending_Sessions_tail,
566 plugin->pending_Sessions_tail, queue);
567 plugin->pendingsessions ++;
573 free_acks (struct FragmentMessage * pm){
574 struct AckQueue * fq;
575 while (pm->head != NULL){
577 GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq);
584 delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc){
585 struct Plugin * plugin = cls;
586 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
588 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
591 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
592 plugin->server_write_task
593 = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
594 plugin->server_stdin_handle,
601 struct GNUNET_TIME_Relative
602 get_next_frag_timeout (struct FragmentMessage * fm)
604 return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
609 * Function to get the timeout value for acks for this session
612 struct GNUNET_TIME_Relative
613 get_ack_timeout (struct FragmentMessage * fm){
614 struct GNUNET_TIME_Relative timeout;
615 timeout.rel_value = FRAGMENT_TIMEOUT;
621 * Function to set the timer for the next timeout of the fragment queue
624 check_next_fragment_timeout (struct Plugin * plugin){
625 struct FragmentMessage * fm;
626 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK){
627 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
629 fm = plugin->pending_Fragment_Messages_head;
631 plugin->server_write_task = GNUNET_SCHEDULER_add_delayed(get_next_frag_timeout(fm), &delay_fragment_task, plugin);
637 * Function to get the next queued Session, removes the session from the queue
640 static struct Session *
641 get_next_queue_Session (struct Plugin * plugin){
642 struct Session * session;
643 struct Sessionqueue * sessionqueue;
644 struct Sessionqueue * sessionqueue_alt;
645 struct PendingMessage * pm;
646 sessionqueue = plugin->pending_Sessions;
647 while (sessionqueue != NULL){
648 session = sessionqueue->content;
649 pm = session->pending_message;
651 //check for message timeout
652 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
653 //check if session has no message in the fragment queue
654 if (! session->has_fragment){
655 plugin->pendingsessions --;
656 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
657 plugin->pending_Sessions_tail, sessionqueue);
658 GNUNET_free(sessionqueue);
662 sessionqueue = sessionqueue->next;
666 session->pending_message = NULL;
667 //call the cont func that it did not work
668 if (pm->transmit_cont != NULL)
669 pm->transmit_cont (pm->transmit_cont_cls,
670 &(session->target), GNUNET_SYSERR);
671 GNUNET_free(pm->msg);
674 sessionqueue_alt = sessionqueue;
675 sessionqueue = sessionqueue->next;
676 plugin->pendingsessions --;
677 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
678 plugin->pending_Sessions_tail, sessionqueue_alt);
680 GNUNET_free(sessionqueue_alt);
691 * Function to sort the message into the message fragment queue
694 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
695 struct FragmentMessage * fm2;
696 //sort into the list at the right position
698 fm2 = plugin->pending_Fragment_Messages_head;
701 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
708 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
709 plugin->pending_Fragment_Messages_tail,fm2,fm);
714 * Function to check if there is some space in the fragment queue
718 check_fragment_queue (struct Plugin * plugin){
719 struct Session * session;
720 struct FragmentMessage * fm;
722 struct PendingMessage * pm;
724 if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
725 session = get_next_queue_Session(plugin);
726 if (session != NULL){
727 pm = session->pending_message;
728 session->pending_message = NULL;
729 session->has_fragment = 1;
730 GNUNET_assert(pm != NULL);
732 fm = GNUNET_malloc(sizeof(struct FragmentMessage));
733 fm->message_size = pm->message_size;
735 fm->session = session;
736 fm->timeout.abs_value = pm->timeout.abs_value;
738 fm->next_ack = GNUNET_TIME_absolute_get();
740 if (pm->transmit_cont != NULL)
741 pm->transmit_cont (pm->transmit_cont_cls,
742 &(session->target), GNUNET_OK);
745 sort_fragment_into_queue(plugin,fm);
746 plugin->pending_fragment_messages ++;
748 //generate new message id
749 session->message_id_out = get_next_message_id();
751 //check if timeout changed
752 check_next_fragment_timeout(plugin);
758 * Function called to when wlan helper is ready to get some data
761 * @param GNUNET_SCHEDULER_TaskContext
765 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
768 struct Plugin * plugin = cls;
769 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
773 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
776 struct Session * session;
777 struct FragmentMessage * fm;
778 struct IeeeHeader * wlanheader;
779 struct RadiotapHeader * radioHeader;
780 struct GNUNET_MessageHeader * msgheader;
781 struct FragmentationHeader fragheader;
783 const char * copystart = NULL;
784 uint16_t copysize = 0;
786 struct AckQueue * akt = NULL;
789 fm = plugin->pending_Fragment_Messages_head;
790 GNUNET_assert(fm != NULL);
791 session = fm->session;
792 GNUNET_assert(session != NULL);
794 // test if message timed out
795 if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
797 GNUNET_assert(plugin->pending_fragment_messages > 0);
798 plugin->pending_fragment_messages --;
799 GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
800 plugin->pending_Fragment_Messages_tail, fm);
802 GNUNET_free(fm->msg);
805 check_fragment_queue(plugin);
808 if (fm->message_size > WLAN_MTU) {
809 size += sizeof(struct FragmentationHeader);
810 // check/set for retransmission
811 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
813 // be positive and try again later :-D
814 fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
815 // find first missing fragment
819 //test if ack 0 was already received
821 //if fragment is present, take next
822 if (akt->fragment_num == fm->message_pos) {
825 //next ack is bigger then the fragment number
826 //in case there is something like this: (acks) 1, 2, 5, 6, ...
827 //and we send 3 again, the next number should be 4
828 else if (akt->fragment_num > fm->message_pos) {
839 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
840 fragheader.fragment_off_or_num = htons(fm->message_pos);
841 fragheader.message_id = htonl(session->message_id_out);
843 // start should be smaller then the packet size
844 GNUNET_assert(copyoffset < fm->message_size);
845 copystart = fm->msg + copyoffset;
847 //size of the fragment is either the MTU - overhead
848 //or the missing part of the message in case this is the last fragment
849 copysize = GNUNET_MIN(fm->message_size - copyoffset,
850 WLAN_MTU - sizeof(struct FragmentationHeader));
851 fragheader.header.size = htons(copysize);
852 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
855 //get the next missing fragment
859 //test if ack was already received
861 //if fragment is present, take next
862 if (akt->fragment_num == fm->message_pos) {
865 //next ack is bigger then the fragment number
866 //in case there is something like this: (acks) 1, 2, 5, 6, ...
867 //and we send 3 again, the next number should be 4
868 else if (akt->fragment_num > fm->message_pos) {
875 // there is no need to split
877 copysize = fm->message_size;
881 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
882 + sizeof(struct GNUNET_MessageHeader);
883 msgheader = GNUNET_malloc(size);
884 msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
885 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
887 radioHeader = (struct RadiotapHeader*) &msgheader[1];
888 getRadiotapHeader(radioHeader);
890 wlanheader = (struct IeeeHeader *) &radioHeader[1];
891 getWlanHeader(wlanheader);
894 //could be faster if content is just send and not copyed before
895 //fragmentheader is needed
896 if (fm->message_size > WLAN_MTU){
897 fragheader.message_crc = htons(getcrc16(copystart, copysize));
898 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
899 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
901 memcpy(&wlanheader[1],copystart,copysize);
904 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
905 GNUNET_assert(bytes == size);
907 //check if this was the last fragment of this message, if true then queue at the end of the list
908 if (copysize + copyoffset >= fm->message_size){
909 GNUNET_assert(copysize + copyoffset == fm->message_size);
911 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
912 plugin->pending_Fragment_Messages_tail, fm);
914 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
915 plugin->pending_Fragment_Messages_tail, fm);
916 // if fragments have opimized timeouts
917 //sort_fragment_into_queue(plugin,fm);
920 check_next_fragment_timeout(plugin);
929 * @param msgbuf pointer tor the data
930 * @param msgbuf_size size of the data
932 * @return 32bit crc value
936 getcrc32 (const char *msgbuf,
945 * @param msgbuf pointer tor the data
946 * @param msgbuf_size size of the data
948 * @return 16bit crc value
952 getcrc16 (const char *msgbuf,
959 * Function that can be used by the transport service to transmit
960 * a message using the plugin.
963 * @param target who should receive this message
964 * @param priority how important is the message
965 * @param msgbuf the message to transmit
966 * @param msgbuf_size number of bytes in 'msgbuf'
967 * @param timeout when should we time out
968 * @param session which session must be used (or NULL for "any")
969 * @param addr the address to use (can be NULL if the plugin
970 * is "on its own" (i.e. re-use existing TCP connection))
971 * @param addrlen length of the address in bytes
972 * @param force_address GNUNET_YES if the plugin MUST use the given address,
973 * otherwise the plugin may use other addresses or
974 * existing connections (if available)
975 * @param cont continuation to call once the message has
976 * been transmitted (or if the transport is ready
977 * for the next transmission call; or if the
978 * peer disconnected...)
979 * @param cont_cls closure for cont
980 * @return number of bytes used (on the physical network, with overheads);
981 * -1 on hard errors (i.e. address invalid); 0 is a legal value
982 * and does NOT mean that the message was not transmitted (DV)
985 wlan_plugin_send (void *cls,
986 const struct GNUNET_PeerIdentity * target,
989 unsigned int priority,
990 struct GNUNET_TIME_Relative timeout,
991 struct Session *session,
995 GNUNET_TRANSPORT_TransmitContinuation cont,
998 struct Plugin * plugin = cls;
999 struct PendingMessage * newmsg = NULL;
1000 struct WlanHeader * wlanheader = NULL;
1001 //check if msglen > 0
1002 GNUNET_assert(msgbuf_size > 0);
1004 //get session if needed
1005 if (session == NULL) {
1006 if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
1007 session = get_Session(plugin, addr);
1009 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1010 _("Wlan Address len %d is wrong\n"),
1016 //TODO target "problem" not solved
1017 session->target = *target;
1020 //first queue session
1021 queue_Session(plugin, session);
1023 //queue message in session
1024 if (session->pending_message == NULL){
1025 newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1026 (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1027 wlanheader = (struct WlanHeader *) newmsg->msg;
1028 //copy msg to buffer, not fragmented / segmented yet, but with message header
1029 wlanheader->header.size = htons(msgbuf_size);
1030 wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
1031 wlanheader->target = *target;
1032 wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
1033 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1034 newmsg->transmit_cont = cont;
1035 newmsg->transmit_cont_cls = cont_cls;
1036 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1037 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1039 //TODO if message is send while hello is still pending, other cases should not occur
1041 check_fragment_queue(plugin);
1042 //FIXME not the correct size
1050 * Function that can be used to force the plugin to disconnect
1051 * from the given peer and cancel all previous transmissions
1052 * (and their continuation).
1054 * @param cls closure
1055 * @param target peer from which to disconnect
1058 wlan_plugin_disconnect (void *cls,
1059 const struct GNUNET_PeerIdentity *target)
1061 struct Plugin *plugin = cls;
1062 struct Sessionqueue * queue = plugin->sessions;
1063 struct Sessionqueue * lastitem = NULL;
1064 struct PendingMessage * pm;
1066 // just look at all the session for the needed one
1067 while (queue != NULL){
1068 // content is never NULL
1069 GNUNET_assert (queue->content == NULL);
1070 if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0)
1073 // remove PendingMessage
1074 pm = queue->content->pending_message;
1075 GNUNET_free(pm->msg);
1078 GNUNET_free(queue->content);
1079 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1086 queue = queue->next;
1092 * Convert the transports address to a nice, human-readable
1095 * @param cls closure
1096 * @param type name of the transport that generated the address
1097 * @param addr one of the addresses of the host, NULL for the last address
1098 * the specific address format depends on the transport
1099 * @param addrlen length of the address
1100 * @param numeric should (IP) addresses be displayed in numeric form?
1101 * @param timeout after how long should we give up?
1102 * @param asc function to call on each string
1103 * @param asc_cls closure for asc
1106 wlan_plugin_address_pretty_printer (void *cls,
1111 struct GNUNET_TIME_Relative timeout,
1112 GNUNET_TRANSPORT_AddressStringCallback
1116 const unsigned char * input;
1118 GNUNET_assert(cls !=NULL);
1121 /* invalid address (MAC addresses have 6 bytes) */
1123 asc (asc_cls, NULL);
1126 input = (const unsigned char*) addr;
1127 GNUNET_snprintf (ret,
1129 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1131 input[0], input[1], input[2], input[3], input[4], input[5]);
1138 * Another peer has suggested an address for this
1139 * peer and transport plugin. Check that this could be a valid
1140 * address. If so, consider adding it to the list
1143 * @param cls closure
1144 * @param addr pointer to the address
1145 * @param addrlen length of addr
1146 * @return GNUNET_OK if this is a plausible address for this peer
1152 wlan_plugin_address_suggested (void *cls,
1156 //struct Plugin *plugin = cls;
1158 /* check if the address is plausible; if so,
1159 add it to our list! */
1161 GNUNET_assert(cls !=NULL);
1162 //FIXME mitm is not checked
1163 //Mac Adress has 6 bytes
1165 /* TODO check for bad addresses like milticast, broadcast, etc */
1168 return GNUNET_SYSERR;
1171 return GNUNET_SYSERR;
1176 * Function called for a quick conversion of the binary address to
1177 * a numeric address. Note that the caller must not free the
1178 * address and that the next call to this function is allowed
1179 * to override the address again.
1181 * @param cls closure
1182 * @param addr binary address
1183 * @param addrlen length of the address
1184 * @return string representing the same address
1187 wlan_plugin_address_to_string (void *cls,
1192 const unsigned char * input;
1194 GNUNET_assert(cls !=NULL);
1197 /* invalid address (MAC addresses have 6 bytes) */
1201 input = (const unsigned char*) addr;
1202 GNUNET_snprintf (ret,
1204 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1206 input[0], input[1], input[2], input[3], input[4], input[5]);
1207 return GNUNET_strdup (ret);
1213 * Function used for to process the data from the suid process
1218 wlan_process_helper (void *cls,
1220 const struct GNUNET_MessageHeader *hdr)
1222 struct Plugin *plugin = cls;
1223 if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
1225 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
1227 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
1229 if (hdr->size == 6){
1230 plugin->mac_address = GNUNET_malloc(6);
1231 memcpy(plugin->mac_address, &hdr[1],6);
1232 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1233 plugin->env->notify_address (plugin->env->cls,
1235 &plugin->mac_address, sizeof(plugin->mac_address),
1236 GNUNET_TIME_UNIT_FOREVER_REL);
1238 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
1249 wlan_plugin_helper_read (void *cls,
1250 const struct GNUNET_SCHEDULER_TaskContext *tc)
1252 struct Plugin *plugin = cls;
1253 char mybuf[WLAN_MTU];
1256 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1258 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1259 mybuf, sizeof(mybuf));
1263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1268 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1269 mybuf, bytes, 0, GNUNET_NO);
1275 * Start the gnunet-wlan-helper process.
1277 * @param plugin the transport plugin
1279 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1282 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1285 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1286 if (plugin->server_stdout == NULL)
1287 return GNUNET_SYSERR;
1289 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1290 if (plugin->server_stdin == NULL)
1291 return GNUNET_SYSERR;
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1295 "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1297 /* Start the server process */
1298 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
1299 if (plugin->server_proc == NULL)
1302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1303 "Failed to start gnunet-wlan-helper process\n");
1305 return GNUNET_SYSERR;
1307 /* Close the write end of the read pipe */
1308 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1310 /* Close the read end of the write pipe */
1311 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1313 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1314 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
1316 plugin->server_read_task =
1317 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1318 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1325 * Entry point for the plugin.
1327 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1328 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1331 gnunet_plugin_transport_wlan_init (void *cls)
1333 struct GNUNET_SERVICE_Context *service;
1334 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1335 struct GNUNET_TRANSPORT_PluginFunctions *api;
1336 struct Plugin *plugin;
1338 GNUNET_assert(cls !=NULL);
1340 service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
1341 if (service == NULL){
1342 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1343 _("Failed to start service for `%s' transport plugin.\n"),
1348 plugin = GNUNET_malloc (sizeof (struct Plugin));
1350 plugin->pendingsessions = 0;
1351 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1352 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1354 wlan_transport_start_wlan_helper(plugin);
1355 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1357 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1358 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1360 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1362 api->send = &wlan_plugin_send;
1363 api->disconnect = &wlan_plugin_disconnect;
1364 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1365 api->check_address = &wlan_plugin_address_suggested;
1366 api->address_to_string = &wlan_plugin_address_to_string;
1369 start_next_message_id();
1376 * Exit point from the plugin.
1380 gnunet_plugin_transport_wlan_done (void *cls)
1382 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1383 struct Plugin *plugin = api->cls;
1385 GNUNET_assert(cls !=NULL);
1387 GNUNET_free_non_null(plugin->mac_address);
1388 GNUNET_free (plugin);
1393 /* end of plugin_transport_wlan.c */