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 "plugin_transport.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
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 uint pendingsessions;
173 struct Sessionqueue * next;
174 struct Sessionqueue * prev;
175 struct Session * content;
182 struct FragmentQueue * next;
183 struct FragmentQueue * prev;
188 * Session handle for connections.
196 struct SessionHeader header;
199 * Pointer to the global plugin struct.
201 struct Plugin *plugin;
204 * Messages currently pending for transmission
205 * to this peer, if any.
207 struct PendingMessage *pending_messages_head;
210 * Messages currently pending for transmission
211 * to this peer, if any.
213 struct PendingMessage *pending_messages_tail;
216 * To whom are we talking to (set to our identity
217 * if we are still waiting for the welcome message)
219 struct GNUNET_PeerIdentity target;
222 * encapsulation of the data
224 //struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
232 * Address of the other peer (either based on our 'connect'
233 * call or on our 'accept' call).
238 * Last activity on this connection. Used to select preferred
241 struct GNUNET_TIME_Absolute last_activity;
244 * current number for message incoming , to distinguish between the messages
246 uint32_t message_id_in;
249 * current number for message outgoing, to distinguish between the messages
251 uint32_t message_id_out;
257 * Information kept for each message that is yet to
260 struct PendingMessage
264 * This is a doubly-linked list.
266 struct PendingMessage *next;
269 * This is a doubly-linked list.
271 struct PendingMessage *prev;
274 * The pending message
279 * Continuation function to call once the message
280 * has been sent. Can be NULL if there is no
281 * continuation to call.
283 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
286 * Cls for transmit_cont
288 void * transmit_cont_cls;
291 * Timeout value for the pending message.
293 struct GNUNET_TIME_Absolute timeout;
296 * Timeout value for the pending fragments.
297 * Stores the time when the last msg fragment ack was received
299 struct GNUNET_TIME_Absolute last_ack;
302 * Sorted queue with the acks received for fragments; head
305 struct FragmentQueue * head;
308 * Sorted queue with the acks received for fragments; tail
311 struct FragmentQueue * tail;
314 * Size of the message
319 * pos / next fragment number in the message, for fragmentation/segmentation,
320 * some acks can be missing but there is still time
322 uint32_t message_pos;
327 * Header for messages which need fragmentation
332 struct GNUNET_MessageHeader header;
335 * checksum/error correction
337 uint32_t crc GNUNET_PACKED;
340 * To whom are we talking to (set to our identity
341 * if we are still waiting for the welcome message)
343 struct GNUNET_PeerIdentity target;
345 // followed by payload
350 * Header for messages which need fragmentation
352 struct FragmentationHeader
355 struct GNUNET_MessageHeader header;
358 * To whom are we talking to (set to our identity
359 * if we are still waiting for the welcome message)
361 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
364 * ID of message, to distinguish between the messages, picked randomly.
366 uint32_t message_id GNUNET_PACKED;
369 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
371 uint16_t fragment_off_or_num GNUNET_PACKED;
374 * CRC of fragment (for error checking)
376 uint16_t message_crc GNUNET_PACKED;
380 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
381 * // 0x2 has data (not only ack)
382 * // 0x4 last fragment of message
385 // uint32_t flags GNUNET_PACKED;
388 * checksum/error correction
390 // uint32_t crc GNUNET_PACKED;
392 // followed by payload unless ACK
396 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
398 int getRadiotapHeader (struct RadiotapHeader * Header);
399 int getWlanHeader (struct IeeeHeader * Header);
400 static int wlan_plugin_address_suggested (void *cls,
403 uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
406 * get the next message number, at the moment just a random one
411 get_next_message_id()
413 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
417 * start next message number generator
421 start_next_message_id()
423 //GNUNET_CRYPTO_random_init;
428 * get Session from address
432 //TODO add other possibilities to find the right session (are there other?)
433 static struct Session *
434 get_Session (struct Plugin *plugin,
437 struct Sessionqueue * queue = plugin->sessions;
438 struct Sessionqueue * lastitem = NULL;
441 //just look at all the session for the needed one
442 while (queue != NULL){
443 // content is never NULL
444 GNUNET_assert (queue->content == NULL);
445 char * addr2 = queue->content->addr;
446 if (memcmp(addr, addr2, 6) == 0)
449 return queue->content;
456 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
458 GNUNET_CONTAINER_DLL_insert(plugin->sessions, plugin->sessions_tail, queue);
460 queue->content = GNUNET_malloc (sizeof (struct Session));
461 queue->content->plugin = plugin;
462 memcpy(queue->content->addr, addr, 6);
463 queue->content->message_id_out = get_next_message_id();
465 //queue welcome message for new sessions, not realy needed
466 //struct WelcomeMessage welcome;
467 struct PendingMessage *pm;
468 pm = GNUNET_malloc (sizeof (struct PendingMessage) + GNUNET_HELLO_size(* (plugin->env->our_hello)));
469 pm->msg = (const char*) &pm[1];
470 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
471 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
472 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
473 //welcome.clientIdentity = *plugin->env->my_identity;
474 memcpy (&pm[1], * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
475 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
476 GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head,
477 (queue->content)->pending_messages_tail,
479 plugin->pendingsessions ++;
480 GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Sessions, plugin->pending_Sessions_tail, plugin->pending_Sessions_tail, queue);
481 return queue->content;
486 * Queue the session to send data
490 queue_Session (struct Plugin *plugin,
491 struct Session * session)
493 struct Sessionqueue * queue = plugin->pending_Sessions;
494 struct Sessionqueue * lastitem = NULL;
496 while (queue != NULL){
497 // content is never NULL
498 GNUNET_assert (queue->content == NULL);
499 // is session already in queue?
500 if (session == queue->content){
508 // Session is not in the queue
510 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
511 queue->content = session;
514 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
515 plugin->pending_Sessions_tail,
516 plugin->pending_Sessions_tail, queue);
517 plugin->pendingsessions ++;
523 free_acks (struct PendingMessage * pm){
524 struct FragmentQueue * fq;
525 while (pm->head != NULL){
527 GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq);
533 * Function called to when wlan helper is ready to get some data
536 * @param GNUNET_SCHEDULER_TaskContext
540 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
542 struct Plugin * plugin = cls;
545 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
548 struct Session * session;
549 struct Sessionqueue * queue;
550 struct PendingMessage * pm;
551 struct IeeeHeader * wlanheader;
552 struct RadiotapHeader * radioHeader;
553 struct GNUNET_MessageHeader * msgheader;
554 struct FragmentationHeader fragheader;
556 const char * copystart = NULL;
557 uint16_t copysize = 0;
559 struct FragmentQueue * akt = NULL;
564 struct GNUNET_TIME_Absolute nextsend;
565 struct GNUNET_TIME_Relative timeout;
566 struct Sessionqueue * nextsession = NULL;
568 timeout.rel_value = FRAGMENT_TIMEOUT;
569 nextsend = GNUNET_TIME_absolute_get_forever();
571 queue = plugin->pending_Sessions;
573 // check if the are some pending sessions/messages ...
574 GNUNET_assert(queue != NULL);
576 session = queue->content;
577 GNUNET_assert(session != NULL);
579 pm = session->pending_messages_head;
580 GNUNET_assert(pm != NULL);
582 // get next valid session
583 // check if this session is only waiting to receive the acks for an already send fragments to finish it
584 // timeout is not reached
585 for (i = 0; i < plugin->pendingsessions; i++){
587 // check if the are some pending sessions/messages ...
588 GNUNET_assert(queue != NULL);
590 session = queue->content;
591 GNUNET_assert(session != NULL);
593 pm = session->pending_messages_head;
594 GNUNET_assert(pm != NULL);
597 nextsession = queue->next;
598 // test if message timed out
599 while (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value == 0){
603 //call the cont func that it did not work
604 if (pm->transmit_cont != NULL)
605 pm->transmit_cont (pm->transmit_cont_cls,
606 &(session->target), GNUNET_SYSERR);
608 GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
609 session->pending_messages_tail,
613 //test if there are no more messages pending for this session
614 if (session->pending_messages_head == NULL){
616 //test if tail is null too
617 GNUNET_assert(session->pending_messages_tail == NULL);
619 plugin->pendingsessions --;
620 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
626 pm = session->pending_messages_head;
630 // restore next session if necessary
634 //there are no more messages in this session
639 // test if retransmit is needed
640 if (GNUNET_TIME_absolute_get_duration(pm->last_ack).rel_value < FRAGMENT_TIMEOUT) {
641 // get last offset for this message
642 copyoffset = pm->message_size /(WLAN_MTU - sizeof(struct FragmentationHeader));
643 // one more is the end
645 // test if it is not the end
646 if (copyoffset > pm->message_pos){
651 nextsend = GNUNET_TIME_absolute_min(GNUNET_TIME_absolute_add(pm->last_ack, timeout), nextsend);
653 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
655 GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
656 plugin->pending_Sessions_tail,
657 plugin->pending_Sessions_tail, queue);
659 //get next pending session
670 //test if there is one session to send something
671 if (nextsession != NULL){
674 // check if the are some pending sessions/messages ...
675 GNUNET_assert(queue != NULL);
677 session = queue->content;
678 GNUNET_assert(session != NULL);
680 pm = session->pending_messages_head;
681 GNUNET_assert(pm != NULL);
683 //nothing to send at the moment
684 plugin->server_read_task =
685 GNUNET_SCHEDULER_add_delayed (plugin->env->sched,
686 GNUNET_TIME_absolute_get_remaining(nextsend),
687 &do_transmit, plugin);
693 if (pm->message_size > WLAN_MTU) {
694 size += sizeof(struct FragmentationHeader);
695 // check for retransmission
696 if (GNUNET_TIME_absolute_get_duration(pm->last_ack).rel_value > FRAGMENT_TIMEOUT) {
698 // be positive and try again later :-D
699 pm->last_ack = GNUNET_TIME_absolute_get();
700 // find first missing fragment
705 //test if ack 0 was already received
707 //if fragment is present, take next
708 if (akt->fragment_num == pm->message_pos) {
711 //next ack is bigger then the fragment number
712 //in case there is something like this: (acks) 1, 2, 5, 6, ...
713 //and we send 3 again, the next number should be 4
714 if (akt->fragment_num > pm->message_pos) {
725 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * pm->message_pos;
726 fragheader.fragment_off_or_num = pm->message_pos;
727 fragheader.message_id = session->message_id_out;
729 // start should be smaller then the packet size
730 //TODO send some other data if everything was send but not all acks are present
731 GNUNET_assert(copyoffset < pm->message_size);
732 copystart = pm->msg + copyoffset;
734 //size of the fragment is either the MTU - overhead
735 //or the missing part of the message in case this is the last fragment
736 copysize = GNUNET_MIN(pm->message_size - copyoffset,
737 WLAN_MTU - sizeof(struct FragmentationHeader));
738 fragheader.header.size = copysize;
739 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
741 //get the next missing fragment
746 //test if ack was already received
748 //if fragment is present, take next
749 if (akt->fragment_num == pm->message_pos) {
752 //next ack is bigger then the fragment number
753 //in case there is something like this: (acks) 1, 2, 5, 6, ...
754 //and we send 3 again, the next number should be 4
755 if (akt->fragment_num > pm->message_pos) {
764 // there is no need to split
766 copysize = pm->message_size;
769 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
770 + sizeof(struct GNUNET_MessageHeader);
771 msgheader = GNUNET_malloc(size);
772 msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
773 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
775 radioHeader = (struct RadiotapHeader*) &msgheader[1];
776 getRadiotapHeader(radioHeader);
778 wlanheader = (struct IeeeHeader *) &radioHeader[1];
779 getWlanHeader(wlanheader);
782 //could be faster if content is just send and not copyed before
783 //fragmentheader is needed
784 if (pm->message_size > WLAN_MTU){
785 fragheader.message_crc = getcrc16(copystart, copysize);
786 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
787 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
789 memcpy(&wlanheader[1],copystart,copysize);
792 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
806 //plugin->server_read_task =
807 //GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
808 // GNUNET_TIME_UNIT_FOREVER_REL,
809 // plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
816 * If we have pending messages, ask the server to
817 * transmit them (schedule the respective tasks, etc.)
819 * @param Plugin env to get everything needed
822 process_pending_messages (struct Plugin * plugin)
824 struct Sessionqueue * queue;
825 struct Session * session;
827 if (plugin->pending_Sessions == NULL)
830 queue = plugin->pending_Sessions;
831 //contet should not be empty
832 GNUNET_assert(queue->content != NULL);
834 session = queue->content;
835 //pending sessions should have some msg
836 GNUNET_assert(session->pending_messages_head != NULL);
838 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
839 plugin->server_write_task
840 = GNUNET_SCHEDULER_add_write_file(plugin->env->sched,
841 GNUNET_TIME_UNIT_FOREVER_REL,
842 plugin->server_stdin_handle,
851 * @param msgbuf pointer tor the data
852 * @param msgbuf_size size of the data
854 * @return 32bit crc value
858 getcrc32 (const char *msgbuf,
867 * @param msgbuf pointer tor the data
868 * @param msgbuf_size size of the data
870 * @return 16bit crc value
874 getcrc16 (const char *msgbuf,
881 * Function that can be used by the transport service to transmit
882 * a message using the plugin.
885 * @param target who should receive this message
886 * @param priority how important is the message
887 * @param msgbuf the message to transmit
888 * @param msgbuf_size number of bytes in 'msgbuf'
889 * @param timeout when should we time out
890 * @param session which session must be used (or NULL for "any")
891 * @param addr the address to use (can be NULL if the plugin
892 * is "on its own" (i.e. re-use existing TCP connection))
893 * @param addrlen length of the address in bytes
894 * @param force_address GNUNET_YES if the plugin MUST use the given address,
895 * otherwise the plugin may use other addresses or
896 * existing connections (if available)
897 * @param cont continuation to call once the message has
898 * been transmitted (or if the transport is ready
899 * for the next transmission call; or if the
900 * peer disconnected...)
901 * @param cont_cls closure for cont
902 * @return number of bytes used (on the physical network, with overheads);
903 * -1 on hard errors (i.e. address invalid); 0 is a legal value
904 * and does NOT mean that the message was not transmitted (DV)
907 wlan_plugin_send (void *cls,
908 const struct GNUNET_PeerIdentity * target,
911 unsigned int priority,
912 struct GNUNET_TIME_Relative timeout,
913 struct Session *session,
917 GNUNET_TRANSPORT_TransmitContinuation cont,
920 struct Plugin * plugin = cls;
921 struct PendingMessage * newmsg = NULL;
922 struct WlanHeader * wlanheader = NULL;
923 //check if msglen > 0
924 GNUNET_assert(msgbuf_size > 0);
926 //get session if needed
927 if (session == NULL) {
928 if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
929 session = get_Session(plugin, addr);
931 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
932 _("Wlan Address len %d is wrong\n"),
938 //TODO target "problem" not solved
939 session->target = *target;
942 //first queue session
943 queue_Session(plugin, session);
945 //queue message in session
946 newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size + sizeof(struct WlanHeader));
947 newmsg->msg = (const char*) &newmsg[1];
948 wlanheader = (struct WlanHeader *) &newmsg[1];
949 //copy msg to buffer, not fragmented / segmented yet, but with message header
950 wlanheader->header.size = msgbuf_size;
951 wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
952 wlanheader->target = *target;
953 wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
954 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
955 newmsg->transmit_cont = cont;
956 newmsg->transmit_cont_cls = cont_cls;
957 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
958 newmsg->message_pos = 0;
959 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
962 //check if queue is empty
963 struct PendingMessage * tailmsg;
964 tailmsg = session->pending_messages_tail;
966 //new tail is the new msg
967 session->pending_messages_tail = newmsg;
968 newmsg->prev = tailmsg;
970 //test if tail was not NULL (queue is empty)
971 if (tailmsg == NULL){
972 // head should be NULL too
973 GNUNET_assert(session->pending_messages_head == NULL);
975 session->pending_messages_head = newmsg;
978 //next at the tail should be NULL
979 GNUNET_assert(tailmsg->next == NULL);
982 tailmsg->next = newmsg;
985 process_pending_messages(plugin);
988 //FIXME not the correct size
996 * Function that can be used to force the plugin to disconnect
997 * from the given peer and cancel all previous transmissions
998 * (and their continuation).
1000 * @param cls closure
1001 * @param target peer from which to disconnect
1004 wlan_plugin_disconnect (void *cls,
1005 const struct GNUNET_PeerIdentity *target)
1007 struct Plugin *plugin = cls;
1008 struct Sessionqueue * queue = plugin->sessions;
1009 struct Sessionqueue * lastitem = NULL;
1010 struct PendingMessage * pm;
1012 // just look at all the session for the needed one
1013 while (queue != NULL){
1014 // content is never NULL
1015 GNUNET_assert (queue->content == NULL);
1016 if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0)
1019 // remove PendingMessage
1020 while (queue->content->pending_messages_head != NULL){
1021 pm = queue->content->pending_messages_head;
1023 GNUNET_CONTAINER_DLL_remove(queue->content->pending_messages_head,queue->content->pending_messages_tail, pm);
1028 GNUNET_free(queue->content);
1029 GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1036 queue = queue->next;
1042 * Convert the transports address to a nice, human-readable
1045 * @param cls closure
1046 * @param type name of the transport that generated the address
1047 * @param addr one of the addresses of the host, NULL for the last address
1048 * the specific address format depends on the transport
1049 * @param addrlen length of the address
1050 * @param numeric should (IP) addresses be displayed in numeric form?
1051 * @param timeout after how long should we give up?
1052 * @param asc function to call on each string
1053 * @param asc_cls closure for asc
1056 wlan_plugin_address_pretty_printer (void *cls,
1061 struct GNUNET_TIME_Relative timeout,
1062 GNUNET_TRANSPORT_AddressStringCallback
1066 const unsigned char * input;
1068 GNUNET_assert(cls !=NULL);
1071 /* invalid address (MAC addresses have 6 bytes) */
1073 asc (asc_cls, NULL);
1076 input = (const unsigned char*) addr;
1077 GNUNET_snprintf (ret,
1079 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1081 input[0], input[1], input[2], input[3], input[4], input[5]);
1088 * Another peer has suggested an address for this
1089 * peer and transport plugin. Check that this could be a valid
1090 * address. If so, consider adding it to the list
1093 * @param cls closure
1094 * @param addr pointer to the address
1095 * @param addrlen length of addr
1096 * @return GNUNET_OK if this is a plausible address for this peer
1102 wlan_plugin_address_suggested (void *cls,
1106 //struct Plugin *plugin = cls;
1108 /* check if the address is plausible; if so,
1109 add it to our list! */
1111 GNUNET_assert(cls !=NULL);
1112 //FIXME mitm is not checked
1113 //Mac Adress has 6 bytes
1115 /* TODO check for bad addresses like milticast, broadcast, etc */
1118 return GNUNET_SYSERR;
1121 return GNUNET_SYSERR;
1126 * Function called for a quick conversion of the binary address to
1127 * a numeric address. Note that the caller must not free the
1128 * address and that the next call to this function is allowed
1129 * to override the address again.
1131 * @param cls closure
1132 * @param addr binary address
1133 * @param addrlen length of the address
1134 * @return string representing the same address
1137 wlan_plugin_address_to_string (void *cls,
1142 const unsigned char * input;
1144 GNUNET_assert(cls !=NULL);
1147 /* invalid address (MAC addresses have 6 bytes) */
1151 input = (const unsigned char*) addr;
1152 GNUNET_snprintf (ret,
1154 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1156 input[0], input[1], input[2], input[3], input[4], input[5]);
1157 return GNUNET_strdup (ret);
1163 * Function used for to process the data from the suid process
1168 wlan_process_helper (void *cls,
1170 const struct GNUNET_MessageHeader *hdr)
1172 struct Plugin *plugin = cls;
1173 if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
1175 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
1177 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
1179 if (hdr->size == 6){
1180 plugin->mac_address = GNUNET_malloc(6);
1181 memcpy(plugin->mac_address, &hdr[1],6);
1182 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1183 plugin->env->notify_address (plugin->env->cls,
1185 &plugin->mac_address, sizeof(plugin->mac_address),
1186 GNUNET_TIME_UNIT_FOREVER_REL);
1188 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
1199 wlan_plugin_helper_read (void *cls,
1200 const struct GNUNET_SCHEDULER_TaskContext *tc)
1202 struct Plugin *plugin = cls;
1203 char mybuf[WLAN_MTU];
1206 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1208 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1209 mybuf, sizeof(mybuf));
1213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1218 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1219 mybuf, bytes, 0, GNUNET_NO);
1225 * Start the gnunet-wlan-helper process.
1227 * @param plugin the transport plugin
1229 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1232 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1235 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1236 if (plugin->server_stdout == NULL)
1237 return GNUNET_SYSERR;
1239 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1240 if (plugin->server_stdin == NULL)
1241 return GNUNET_SYSERR;
1244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1245 "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1247 /* Start the server process */
1248 plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
1249 if (plugin->server_proc == NULL)
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253 "Failed to start gnunet-wlan-helper process\n");
1255 return GNUNET_SYSERR;
1257 /* Close the write end of the read pipe */
1258 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1260 /* Close the read end of the write pipe */
1261 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1263 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1264 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
1266 plugin->server_read_task =
1267 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
1268 GNUNET_TIME_UNIT_FOREVER_REL,
1269 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1276 * Entry point for the plugin.
1278 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1279 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1282 gnunet_plugin_transport_wlan_init (void *cls)
1284 struct GNUNET_SERVICE_Context *service;
1285 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1286 struct GNUNET_TRANSPORT_PluginFunctions *api;
1287 struct Plugin *plugin;
1289 GNUNET_assert(cls !=NULL);
1291 service = GNUNET_SERVICE_start ("transport-wlan", env->sched, env->cfg);
1292 if (service == NULL){
1293 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1294 _("Failed to start service for `%s' transport plugin.\n"),
1299 plugin = GNUNET_malloc (sizeof (struct Plugin));
1301 plugin->pendingsessions = 0;
1303 wlan_transport_start_wlan_helper(plugin);
1304 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1306 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1307 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1309 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1311 api->send = &wlan_plugin_send;
1312 api->disconnect = &wlan_plugin_disconnect;
1313 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1314 api->check_address = &wlan_plugin_address_suggested;
1315 api->address_to_string = &wlan_plugin_address_to_string;
1317 start_next_message_id();
1324 * Exit point from the plugin.
1328 gnunet_plugin_transport_wlan_done (void *cls)
1330 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1331 struct Plugin *plugin = api->cls;
1333 GNUNET_assert(cls !=NULL);
1335 GNUNET_free_non_null(plugin->mac_address);
1336 GNUNET_free (plugin);
1341 /* end of plugin_transport_wlan.c */