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"
37 #define PROTOCOL_PREFIX "wlan"
40 * Max size of packet from helper
45 * Time until retransmission of a fragment in ms
48 #define FRAGMENT_TIMEOUT 1000
51 #define DEBUG_wlan GNUNET_NO
54 * After how long do we expire an address that we
55 * learned from another peer if it is not reconfirmed
58 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
61 * Initial handshake message for a session.
66 * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
68 struct GNUNET_MessageHeader header;
71 * Identity of the node connecting (TCP client)
73 struct GNUNET_PeerIdentity clientIdentity;
78 * Encapsulation of all of the state of the plugin.
85 struct GNUNET_TRANSPORT_PluginEnvironment *env;
88 * List of open sessions.
90 struct Session *sessions;
93 * encapsulation to the local wlan server prog
96 struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
100 * stdout pipe handle for the gnunet-wlan-helper process
102 struct GNUNET_DISK_PipeHandle *server_stdout;
105 * stdout file handle for the gnunet-wlan-helper process
107 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
110 * stdin pipe handle for the gnunet-wlan-helper process
112 struct GNUNET_DISK_PipeHandle *server_stdin;
115 * stdin file handle for the gnunet-wlan-helper process
117 const struct GNUNET_DISK_FileHandle *server_stdin_handle;
120 * ID of select gnunet-nat-server std read task
122 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
125 * ID of select gnunet-nat-server std read task
127 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
130 * The process id of the server process (if behind NAT)
135 * The interface of the wlan card given to us by the user.
140 * The mac_address of the wlan card given to us by the helper.
145 * Sessions currently pending for transmission
146 * to this peer, if any.
148 struct Sessionqueue * pending_Sessions;
151 * Sessions currently pending for transmission
152 * to this peer, if any.
154 struct Sessionqueue * all_Sessions;
162 struct Sessionqueue * next;
163 struct Sessionqueue * prev;
164 struct Session * content;
171 struct FragmentQueue * next;
172 struct FragmentQueue * prev;
177 * Session handle for connections.
185 struct SessionHeader header;
188 * Pointer to the global plugin struct.
190 struct Plugin *plugin;
193 * Messages currently pending for transmission
194 * to this peer, if any.
196 struct PendingMessage *pending_messages_head;
199 * Messages currently pending for transmission
200 * to this peer, if any.
202 struct PendingMessage *pending_messages_tail;
205 * To whom are we talking to (set to our identity
206 * if we are still waiting for the welcome message)
208 struct GNUNET_PeerIdentity target;
211 * encapsulation of the data
213 struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
221 * Address of the other peer (either based on our 'connect'
222 * call or on our 'accept' call).
227 * Last activity on this connection. Used to select preferred
230 struct GNUNET_TIME_Absolute last_activity;
233 * current number for message incoming , to distinguish between the messages
235 uint32_t message_id_in;
238 * current number for message outgoing, to distinguish between the messages
240 uint32_t message_id_out;
246 * Information kept for each message that is yet to
249 struct PendingMessage
253 * This is a doubly-linked list.
255 struct PendingMessage *next;
258 * This is a doubly-linked list.
260 struct PendingMessage *prev;
263 * The pending message
268 * Continuation function to call once the message
269 * has been sent. Can be NULL if there is no
270 * continuation to call.
272 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
275 * Cls for transmit_cont
277 void * transmit_cont_cls;
280 * Timeout value for the pending message.
282 struct GNUNET_TIME_Absolute timeout;
285 * Timeout value for the pending fragments.
286 * Stores the time when the last msg fragment ack was received
288 struct GNUNET_TIME_Absolute last_ack;
291 * Sorted queue with the acks received for fragments; head
294 struct FragmentQueue * head;
297 * Sorted queue with the acks received for fragments; tail
300 struct FragmentQueue * tail;
303 * Size of the message
308 * pos / next fragment number in the message, for fragmentation/segmentation,
309 * some acks can be missing but there is still time
311 uint32_t message_pos;
316 * Header for messages which need fragmentation
321 struct GNUNET_MessageHeader header;
324 * checksum/error correction
326 uint32_t crc GNUNET_PACKED;
329 * To whom are we talking to (set to our identity
330 * if we are still waiting for the welcome message)
332 struct GNUNET_PeerIdentity target;
334 // followed by payload
339 * Header for messages which need fragmentation
341 struct FragmentationHeader
344 struct GNUNET_MessageHeader header;
347 * To whom are we talking to (set to our identity
348 * if we are still waiting for the welcome message)
350 // struct GNUNET_PeerIdentity target GNUNET_PACKED;
353 * ID of message, to distinguish between the messages, picked randomly.
355 uint32_t message_id GNUNET_PACKED;
358 * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
360 uint16_t fragment_off_or_num GNUNET_PACKED;
363 * CRC of fragment (for error checking)
365 uint16_t message_crc GNUNET_PACKED;
369 * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
370 * // 0x2 has data (not only ack)
371 * // 0x4 last fragment of message
374 // uint32_t flags GNUNET_PACKED;
377 * checksum/error correction
379 // uint32_t crc GNUNET_PACKED;
381 // followed by payload unless ACK
385 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
387 int getRadiotapHeader (struct RadiotapHeader * Header);
388 int getWlanHeader (struct IeeeHeader * Header);
389 static int wlan_plugin_address_suggested (void *cls,
392 uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
395 * get the next message number, at the moment just a random one
400 get_next_message_id()
402 // FIXME find good random generator
403 if (RAND_MAX < UINT32_MAX){
404 return (random() * random()) % UINT32_MAX;
406 return random() % UINT32_MAX;
411 * start next message number generator
415 start_next_message_id()
418 srand(GNUNET_TIME_absolute_get().value);
423 * get Session from address
427 //TODO add other possibilities to find the right session (are there other?)
428 static struct Session *
429 get_Session (struct Plugin *plugin,
432 struct Sessionqueue * queue = plugin->all_Sessions;
433 struct Sessionqueue * lastitem = NULL;
436 //just look at all the session for the needed one
437 while (queue != NULL){
438 // content is never NULL
439 GNUNET_assert (queue->content == NULL);
440 char * addr2 = queue->content->addr;
441 if (memcmp(addr, addr2, 6) == 0)
444 return queue->content;
451 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
453 if (plugin->all_Sessions == NULL){
455 plugin->all_Sessions = queue;
457 lastitem->next = queue;
458 queue->prev = lastitem;
461 queue->content = GNUNET_malloc (sizeof (struct Session));
462 queue->content->plugin = plugin;
463 memcpy(queue->content->addr, addr, 6);
464 queue->content->message_id_out = get_next_message_id();
466 //queue welcome message for new sessions, not realy needed
467 //struct WelcomeMessage welcome;
468 struct PendingMessage *pm;
469 pm = GNUNET_malloc (sizeof (struct PendingMessage) + GNUNET_HELLO_size(* (plugin->env->our_hello)));
470 pm->msg = (const char*) &pm[1];
471 pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
472 //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
473 //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
474 //welcome.clientIdentity = *plugin->env->my_identity;
475 memcpy (&pm[1], * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
476 pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
477 GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head,
478 (queue->content)->pending_messages_tail,
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 if (plugin->pending_Sessions == NULL){
513 plugin->pending_Sessions = queue;
515 lastitem->next = queue;
516 queue->prev = lastitem;
519 queue->content = session;
524 * Function called to when wlan helper is ready to get some data
527 * @param GNUNET_SCHEDULER_TaskContext
531 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
533 struct Plugin * plugin = cls;
536 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
539 struct Session * session;
540 struct Sessionqueue * queue;
541 struct PendingMessage * pm;
542 struct IeeeHeader * wlanheader;
543 struct RadiotapHeader * radioHeader;
544 struct GNUNET_MessageHeader * msgheader;
545 struct FragmentationHeader fragheader;
547 const char * copystart = NULL;
548 uint16_t copysize = 0;
550 struct FragmentQueue * akt = NULL;
553 queue = plugin->pending_Sessions;
555 //check if the are some pending sessions/messages ...
556 GNUNET_assert(queue != NULL);
558 session = queue->content;
559 GNUNET_assert(session != NULL);
561 pm = session->pending_messages_head;
562 GNUNET_assert(pm != NULL);
564 //check if msg is valid to send
565 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).value > 0){
566 // split msg if to large
568 if (pm->message_size > WLAN_MTU) {
569 size += sizeof(struct FragmentationHeader);
570 // check for retransmission
571 if (GNUNET_TIME_absolute_get_duration(pm->last_ack).value > FRAGMENT_TIMEOUT) {
573 // be positive and try again later :-D
574 pm->last_ack = GNUNET_TIME_absolute_get();
575 // find first missing fragment
580 //test if ack was already received
583 //if fragment is present, take next
584 if (akt->fragment_num == pm->message_pos) {
587 //next ack is bigger then the fragment number
588 //in case there is something like this: (acks) 1, 2, 5, 6, ...
589 //and we send 3 again, the next number should be 4
590 if (akt->fragment_num > pm->message_pos) {
595 //test if this was the last ack
605 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * pm->message_pos;
606 fragheader.fragment_off_or_num = pm->message_pos;
607 fragheader.message_id = session->message_id_out;
609 // start should be smaller then the packet size
610 //TODO send some other data if everything was send but not all acks are present
611 GNUNET_assert(copyoffset < pm->message_size);
612 copystart = pm->msg + copyoffset;
614 //size of the fragment is either the MTU - overhead
615 //or the missing part of the message in case this is the last fragment
616 copysize = GNUNET_MIN(pm->message_size - copyoffset,
617 WLAN_MTU - sizeof(struct FragmentationHeader));
618 fragheader.header.size = copysize;
619 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
621 //get the next missing fragment
626 //test if ack was already received
629 //if fragment is present, take next
630 if (akt->fragment_num == pm->message_pos) {
633 //next ack is bigger then the fragment number
634 //in case there is something like this: (acks) 1, 2, 5, 6, ...
635 //and we send 3 again, the next number should be 4
636 if (akt->fragment_num > pm->message_pos) {
641 //test if this was the last ack
650 // there is no need to split
652 copysize = pm->message_size;
655 size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
656 + sizeof(struct GNUNET_MessageHeader);
657 msgheader = GNUNET_malloc(size);
658 msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
659 msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
661 radioHeader = (struct RadiotapHeader*) &msgheader[1];
662 getRadiotapHeader(radioHeader);
664 wlanheader = (struct IeeeHeader *) &radioHeader[1];
665 getWlanHeader(wlanheader);
668 //could be faster if content is just send and not copyed before
669 //fragmentheader is needed
670 if (pm->message_size > WLAN_MTU){
671 fragheader.message_crc = getcrc16(copystart, copysize);
672 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
673 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
675 memcpy(&wlanheader[1],copystart,copysize);
678 bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
683 //TODO free the queues (acks)
684 GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
685 session->pending_messages_tail,
700 //plugin->server_read_task =
701 //GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
702 // GNUNET_TIME_UNIT_FOREVER_REL,
703 // plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
710 * If we have pending messages, ask the server to
711 * transmit them (schedule the respective tasks, etc.)
713 * @param Plugin env to get everything needed
716 process_pending_messages (struct Plugin * plugin)
718 struct Sessionqueue * queue;
719 struct Session * session;
721 if (plugin->pending_Sessions == NULL)
724 queue = plugin->pending_Sessions;
725 //contet should not be empty
726 GNUNET_assert(queue->content != NULL);
728 session = queue->content;
729 //pending sessions should have some msg
730 GNUNET_assert(session->pending_messages_head != NULL);
732 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
733 plugin->server_write_task
734 = GNUNET_SCHEDULER_add_write_file(plugin->env->sched,
735 GNUNET_TIME_UNIT_FOREVER_REL,
736 plugin->server_stdin_handle,
745 * @param msgbuf pointer tor the data
746 * @param msgbuf_size size of the data
748 * @return 32bit crc value
752 getcrc32 (const char *msgbuf,
761 * @param msgbuf pointer tor the data
762 * @param msgbuf_size size of the data
764 * @return 16bit crc value
768 getcrc16 (const char *msgbuf,
775 * Function that can be used by the transport service to transmit
776 * a message using the plugin.
779 * @param target who should receive this message
780 * @param priority how important is the message
781 * @param msgbuf the message to transmit
782 * @param msgbuf_size number of bytes in 'msgbuf'
783 * @param timeout when should we time out
784 * @param session which session must be used (or NULL for "any")
785 * @param addr the address to use (can be NULL if the plugin
786 * is "on its own" (i.e. re-use existing TCP connection))
787 * @param addrlen length of the address in bytes
788 * @param force_address GNUNET_YES if the plugin MUST use the given address,
789 * otherwise the plugin may use other addresses or
790 * existing connections (if available)
791 * @param cont continuation to call once the message has
792 * been transmitted (or if the transport is ready
793 * for the next transmission call; or if the
794 * peer disconnected...)
795 * @param cont_cls closure for cont
796 * @return number of bytes used (on the physical network, with overheads);
797 * -1 on hard errors (i.e. address invalid); 0 is a legal value
798 * and does NOT mean that the message was not transmitted (DV)
801 wlan_plugin_send (void *cls,
802 const struct GNUNET_PeerIdentity * target,
805 unsigned int priority,
806 struct GNUNET_TIME_Relative timeout,
807 struct Session *session,
811 GNUNET_TRANSPORT_TransmitContinuation cont,
814 struct Plugin * plugin = cls;
815 struct PendingMessage * newmsg = NULL;
816 struct WlanHeader * wlanheader = NULL;
817 //check if msglen > 0
818 GNUNET_assert(msgbuf_size > 0);
820 //get session if needed
821 if (session == NULL) {
822 if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
823 session = get_Session(plugin, addr);
825 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
826 _("Wlan Address len %d is wrong\n"),
832 //TODO target "problem" not solved
833 session->target = *target;
836 //first queue session
837 queue_Session(plugin, session);
839 //queue message in session
840 newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size + sizeof(struct WlanHeader));
841 newmsg->msg = (const char*) &newmsg[1];
842 wlanheader = (struct WlanHeader *) &newmsg[1];
843 //copy msg to buffer, not fragmented / segmented yet, but with message header
844 wlanheader->header.size = msgbuf_size;
845 wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
846 wlanheader->target = *target;
847 wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
848 memcpy(&wlanheader[1], msgbuf, msgbuf_size);
849 newmsg->transmit_cont = cont;
850 newmsg->transmit_cont_cls = cont_cls;
851 newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
852 newmsg->message_pos = 0;
853 newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
856 //check if queue is empty
857 struct PendingMessage * tailmsg;
858 tailmsg = session->pending_messages_tail;
860 //new tail is the new msg
861 session->pending_messages_tail = newmsg;
862 newmsg->prev = tailmsg;
864 //test if tail was not NULL (queue is empty)
865 if (tailmsg == NULL){
866 // head should be NULL too
867 GNUNET_assert(session->pending_messages_head == NULL);
869 session->pending_messages_head = newmsg;
872 //next at the tail should be NULL
873 GNUNET_assert(tailmsg->next == NULL);
876 tailmsg->next = newmsg;
879 process_pending_messages(plugin);
882 //FIXME not the correct size
890 * Function that can be used to force the plugin to disconnect
891 * from the given peer and cancel all previous transmissions
892 * (and their continuation).
895 * @param target peer from which to disconnect
898 wlan_plugin_disconnect (void *cls,
899 const struct GNUNET_PeerIdentity *target)
901 // struct Plugin *plugin = cls;
902 // FIXME make something usefull :-D
907 * Convert the transports address to a nice, human-readable
911 * @param type name of the transport that generated the address
912 * @param addr one of the addresses of the host, NULL for the last address
913 * the specific address format depends on the transport
914 * @param addrlen length of the address
915 * @param numeric should (IP) addresses be displayed in numeric form?
916 * @param timeout after how long should we give up?
917 * @param asc function to call on each string
918 * @param asc_cls closure for asc
921 wlan_plugin_address_pretty_printer (void *cls,
926 struct GNUNET_TIME_Relative timeout,
927 GNUNET_TRANSPORT_AddressStringCallback
931 const unsigned char * input;
933 GNUNET_assert(cls !=NULL);
936 /* invalid address (MAC addresses have 6 bytes) */
941 input = (const unsigned char*) addr;
942 GNUNET_snprintf (ret,
944 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
946 input[0], input[1], input[2], input[3], input[4], input[5]);
953 * Another peer has suggested an address for this
954 * peer and transport plugin. Check that this could be a valid
955 * address. If so, consider adding it to the list
959 * @param addr pointer to the address
960 * @param addrlen length of addr
961 * @return GNUNET_OK if this is a plausible address for this peer
967 wlan_plugin_address_suggested (void *cls,
971 /* struct Plugin *plugin = cls; */
973 /* check if the address is plausible; if so,
974 add it to our list! */
976 GNUNET_assert(cls !=NULL);
978 //Mac Adress has 6 bytes
980 /* TODO check for bad addresses like milticast, broadcast, etc */
983 return GNUNET_SYSERR;
986 return GNUNET_SYSERR;
991 * Function called for a quick conversion of the binary address to
992 * a numeric address. Note that the caller must not free the
993 * address and that the next call to this function is allowed
994 * to override the address again.
997 * @param addr binary address
998 * @param addrlen length of the address
999 * @return string representing the same address
1002 wlan_plugin_address_to_string (void *cls,
1007 const unsigned char * input;
1009 GNUNET_assert(cls !=NULL);
1012 /* invalid address (MAC addresses have 6 bytes) */
1016 input = (const unsigned char*) addr;
1017 GNUNET_snprintf (ret,
1019 "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1021 input[0], input[1], input[2], input[3], input[4], input[5]);
1022 return GNUNET_strdup (ret);
1028 * Function used for to process the data from the suid process
1033 wlan_process_helper (void *cls,
1035 const struct GNUNET_MessageHeader *hdr)
1037 struct Plugin *plugin = cls;
1038 if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
1040 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
1042 } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
1044 if (hdr->size == 6){
1045 plugin->mac_address = GNUNET_malloc(6);
1046 memcpy(plugin->mac_address, &hdr[1],6);
1047 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1048 plugin->env->notify_address (plugin->env->cls,
1050 &plugin->mac_address, sizeof(plugin->mac_address),
1051 GNUNET_TIME_UNIT_FOREVER_REL);
1053 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
1064 wlan_plugin_helper_read (void *cls,
1065 const struct GNUNET_SCHEDULER_TaskContext *tc)
1067 struct Plugin *plugin = cls;
1068 char mybuf[WLAN_MTU];
1071 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1073 bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle,
1074 mybuf, sizeof(mybuf));
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1083 GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1084 mybuf, bytes, 0, GNUNET_NO);
1090 * Start the gnunet-wlan-helper process.
1092 * @param plugin the transport plugin
1094 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1097 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1100 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1101 if (plugin->server_stdout == NULL)
1102 return GNUNET_SYSERR;
1104 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1105 if (plugin->server_stdin == NULL)
1106 return GNUNET_SYSERR;
1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1110 "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1112 /* Start the server process */
1113 plugin->server_pid = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
1114 if (plugin->server_pid == GNUNET_SYSERR)
1117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1118 "Failed to start gnunet-wlan-helper process\n");
1120 return GNUNET_SYSERR;
1122 /* Close the write end of the read pipe */
1123 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1125 /* Close the read end of the write pipe */
1126 GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1128 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1129 plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
1131 plugin->server_read_task =
1132 GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
1133 GNUNET_TIME_UNIT_FOREVER_REL,
1134 plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1141 * Entry point for the plugin.
1143 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1144 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1147 gnunet_plugin_transport_wlan_init (void *cls)
1149 struct GNUNET_SERVICE_Context *service;
1150 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1151 struct GNUNET_TRANSPORT_PluginFunctions *api;
1152 struct Plugin *plugin;
1154 GNUNET_assert(cls !=NULL);
1156 service = GNUNET_SERVICE_start ("transport-wlan", env->sched, env->cfg);
1157 if (service == NULL){
1158 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1159 _("Failed to start service for `%s' transport plugin.\n"),
1164 plugin = GNUNET_malloc (sizeof (struct Plugin));
1167 wlan_transport_start_wlan_helper(plugin);
1168 plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1170 //plugin->all_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1171 //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1173 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1175 api->send = &wlan_plugin_send;
1176 api->disconnect = &wlan_plugin_disconnect;
1177 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1178 api->check_address = &wlan_plugin_address_suggested;
1179 api->address_to_string = &wlan_plugin_address_to_string;
1181 start_next_message_id();
1188 * Exit point from the plugin.
1192 gnunet_plugin_transport_wlan_done (void *cls)
1194 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1195 struct Plugin *plugin = api->cls;
1197 GNUNET_assert(cls !=NULL);
1199 GNUNET_free_non_null(plugin->mac_address);
1200 GNUNET_free (plugin);
1205 /* end of plugin_transport_wlan.c */