The NULL test clearly needs to be before any dereferences.
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
1 /*
2      This file is part of GNUnet
3      (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file transport/plugin_transport_wlan.c
23  * @brief transport plugin for wlan
24  * @author David Brodski
25  */
26
27 #include "platform.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet_transport_service.h"
32 #include "plugin_transport.h"
33 #include "plugin_transport_wlan.h"
34 #include "gnunet_common.h"
35
36 #define PROTOCOL_PREFIX "wlan"
37
38 /**
39  * Max size of packet from helper
40  */
41 #define WLAN_MTU 3000
42
43 #define DEBUG_wlan GNUNET_NO
44
45 /**
46  * After how long do we expire an address that we
47  * learned from another peer if it is not reconfirmed
48  * by anyone?
49  */
50 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
51
52 /**
53  * Initial handshake message for a session.
54  */
55 struct WelcomeMessage
56 {
57   /**
58    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
59    */
60   struct GNUNET_MessageHeader header;
61
62   /**
63    * Identity of the node connecting (TCP client)
64    */
65   struct GNUNET_PeerIdentity clientIdentity;
66
67 };
68
69 /**
70  * Encapsulation of all of the state of the plugin.
71  */
72 struct Plugin
73 {
74   /**
75    * Our environment.
76    */
77   struct GNUNET_TRANSPORT_PluginEnvironment *env;
78
79   /**
80    * List of open sessions.
81    */
82   struct Session *sessions;
83
84   /**
85    * encapsulation to the local wlan server prog
86    */
87
88   struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
89
90
91   /**
92    * stdout pipe handle for the gnunet-wlan-helper process
93    */
94   struct GNUNET_DISK_PipeHandle *server_stdout;
95
96   /**
97    * stdout file handle for the gnunet-wlan-helper process
98    */
99   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
100
101   /**
102    * stdin pipe handle for the gnunet-wlan-helper process
103    */
104   struct GNUNET_DISK_PipeHandle *server_stdin;
105
106   /**
107    * stdin file handle for the gnunet-wlan-helper process
108    */
109   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
110
111   /**
112    * ID of select gnunet-nat-server std read task
113    */
114   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
115
116   /**
117      * ID of select gnunet-nat-server std read task
118      */
119   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
120
121   /**
122    * The process id of the server process (if behind NAT)
123    */
124   pid_t server_pid;
125
126   /**
127    * The interface of the wlan card given to us by the user.
128    */
129   char *interface;
130
131   /**
132    * The mac_address of the wlan card given to us by the helper.
133    */
134   char *mac_address;
135
136   /**
137    * Sessions currently pending for transmission
138    * to this peer, if any.
139    */
140   struct Sessionqueue * pending_Sessions;
141
142   /**
143    * Sessions currently pending for transmission
144    * to this peer, if any.
145    */
146   struct Sessionqueue * all_Sessions;
147
148 };
149
150
151 struct Sessionqueue
152 {
153         struct Sessionqueue * next;
154         struct Sessionqueue * prev;
155         struct Session * content;
156 };
157
158 /**
159  * Session handle for connections.
160  */
161 struct Session
162 {
163
164   /**
165    * API requirement.
166    */
167   struct SessionHeader header;
168
169   /**
170    * Pointer to the global plugin struct.
171    */
172   struct Plugin *plugin;
173
174   /**
175    * Messages currently pending for transmission
176    * to this peer, if any.
177    */
178   struct PendingMessage *pending_messages_head;
179
180   /**
181    * Messages currently pending for transmission
182    * to this peer, if any.
183    */
184   struct PendingMessage *pending_messages_tail;
185
186   /**
187    * To whom are we talking to (set to our identity
188    * if we are still waiting for the welcome message)
189    */
190   struct GNUNET_PeerIdentity target;
191
192   /**
193    * encapsulation of the data
194    */
195   struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
196
197   /**
198    * peer mac address
199    */
200   char addr[6];
201
202   /**
203    * Address of the other peer (either based on our 'connect'
204    * call or on our 'accept' call).
205    */
206   void *connect_addr;
207
208   /**
209    * Last activity on this connection.  Used to select preferred
210    * connection.
211    */
212   struct GNUNET_TIME_Absolute last_activity;
213
214   /**
215    * number of message, to distinguish between the messages
216    */
217   uint16_t message_num_in;
218
219   /**
220    * number of message, to distinguish between the messages
221    */
222   uint16_t message_num_out;
223
224
225 };
226
227 /**
228  * Information kept for each message that is yet to
229  * be transmitted.
230  */
231 struct PendingMessage
232 {
233
234   /**
235    * This is a doubly-linked list.
236    */
237   struct PendingMessage *next;
238
239   /**
240    * This is a doubly-linked list.
241    */
242   struct PendingMessage *prev;
243
244   /**
245    * The pending message
246    */
247   const char *msg;
248
249   /**
250    * Continuation function to call once the message
251    * has been sent.  Can be NULL if there is no
252    * continuation to call.
253    */
254   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
255
256   /**
257    * Cls for transmit_cont
258    */
259   void * transmit_cont_cls;
260
261   /**
262    * Timeout value for the pending message.
263    */
264   struct GNUNET_TIME_Absolute timeout;
265
266   /**
267    * Size of the message
268    */
269   size_t message_size;
270
271   /**
272    * pos in the message, for fragmentation/segmentation
273    */
274   size_t message_pos;
275 };
276
277
278 /**
279  * Header for messages which need fragmentation
280  */
281 struct WlanHeader
282 {
283
284   struct GNUNET_MessageHeader header;
285
286   /**
287    * checksum/error correction
288    */
289   uint32_t crc GNUNET_PACKED;
290
291   /**
292    * To whom are we talking to (set to our identity
293    * if we are still waiting for the welcome message)
294    */
295   struct GNUNET_PeerIdentity target;
296
297   // followed by payload
298
299 };
300
301 /**
302  * Header for messages which need fragmentation
303  */
304 struct FragmentationHeader
305 {
306
307   struct GNUNET_MessageHeader header;
308
309   /**
310    * To whom are we talking to (set to our identity
311    * if we are still waiting for the welcome message)
312    */
313   // struct GNUNET_PeerIdentity target GNUNET_PACKED;
314
315   /**
316    * ID of message, to distinguish between the messages, picked randomly.
317    */
318   uint32_t message_id GNUNET_PACKED;
319
320   /**
321    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
322    */
323   uint16_t fragment_off_or_num GNUNET_PACKED;
324
325   /**
326    * CRC of fragment (for error checking)
327    */
328   uint16_t message_crc GNUNET_PACKED;
329
330   /**
331    * Flags
332    * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
333    * // 0x2 has data (not only ack)
334    * // 0x4 last fragment of message
335    * // 0x8 new message
336    */
337   //  uint32_t flags GNUNET_PACKED;
338
339   /**
340    * checksum/error correction
341    */
342   // uint32_t crc GNUNET_PACKED;
343
344   // followed by payload unless ACK
345
346 };
347
348 enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
349
350 int getRadiotapHeader (struct RadiotapHeader * Header);
351 int getWlanHeader (struct IeeeHeader * Header);
352 static int wlan_plugin_address_suggested (void *cls,
353                                    const void *addr,
354                                    size_t addrlen);
355 /**
356  * get Session from address
357  *
358  */
359
360 //TODO add other possibilities to find the right session (are there other?)
361 static struct Session *
362 get_Session (struct Plugin *plugin,
363              const char * addr)
364 {
365         struct Sessionqueue * queue = plugin->all_Sessions;
366         struct Sessionqueue * lastitem = NULL;
367
368         while (queue != NULL){
369                 // content is never NULL
370                 GNUNET_assert (queue->content == NULL);
371                 char * addr2 = queue->content->addr;
372                 if (memcmp(addr, addr2, 6) == 0)
373                   {
374                     //sesion found
375                     return queue->content;
376                   }
377                 // try next
378                 lastitem = queue;
379                 queue = queue->next;
380         }
381         // new session
382         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
383
384         if (plugin->all_Sessions == NULL){
385                 //is first session
386                 plugin->all_Sessions = queue;
387         } else {
388                 lastitem->next = queue;
389                 queue->prev = lastitem;
390         }
391
392         queue->content = GNUNET_malloc (sizeof (struct Session));
393         queue->content->plugin = plugin;
394         memcpy(queue->content->addr, addr, 6);
395
396         //queue welcome
397         struct WelcomeMessage welcome;
398         struct PendingMessage *pm;
399         pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct WelcomeMessage));
400         pm->msg = (const char*) &pm[1];
401         pm->message_size = sizeof (struct WelcomeMessage);
402         welcome.header.size = htons (sizeof (struct WelcomeMessage));
403         welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
404         welcome.clientIdentity = *plugin->env->my_identity;
405         memcpy (&pm[1], &welcome, sizeof (welcome));
406         pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
407         GNUNET_CONTAINER_DLL_insert ((queue->content)->pending_messages_head,
408                                            (queue->content)->pending_messages_tail,
409                                        pm);
410
411         return queue->content;
412
413 }
414
415 /**
416  * Queue the session to send data
417  */
418
419 static void
420 queue_Session (struct Plugin *plugin,
421                 struct Session * session)
422 {
423         struct Sessionqueue * queue = plugin->pending_Sessions;
424         struct Sessionqueue * lastitem = NULL;
425
426         while (queue != NULL){
427                 // content is never NULL
428                 GNUNET_assert (queue->content == NULL);
429                 // is session already in queue?
430                 if (session == queue->content){
431                         return;
432                 }
433                 // try next
434                 lastitem = queue;
435                 queue = queue->next;
436         }
437
438         // Session is not in the queue
439
440         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
441         if (plugin->pending_Sessions == NULL){
442                         //is first session
443                         plugin->pending_Sessions = queue;
444                 } else {
445                         lastitem->next = queue;
446                         queue->prev = lastitem;
447                 }
448
449         queue->content = session;
450
451 }
452
453 /**
454  * Function called to when wlan helper is ready to get some data
455  *
456  * @param cls closure
457  * @param GNUNET_SCHEDULER_TaskContext
458  */
459
460 static void
461 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
462 {
463   struct Plugin * plugin = cls;
464   ssize_t bytes;
465
466   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
467     return;
468
469   struct Session * session;
470   struct Sessionqueue * queue;
471   struct PendingMessage * pm;
472   struct IeeeHeader * wlanheader;
473   struct RadiotapHeader * radioHeader;
474   struct GNUNET_MessageHeader * msgheader;
475   uint16_t size = 0;
476
477   queue = plugin->pending_Sessions;
478
479   //check if the are some pending sessions/messages ...
480   GNUNET_assert(queue != NULL);
481
482   session = queue->content;
483   GNUNET_assert(session != NULL);
484
485   pm = session->pending_messages_head;
486   GNUNET_assert(pm != NULL);
487
488   //check if msg is valid to send
489   if (GNUNET_TIME_absolute_get_remaining(pm->timeout).value > 0){
490         // fixme split msg if to large
491
492         //increment one, this is a new message
493         session->message_num_out ++;
494         // fixme peer id is needed in each packet
495         size = pm->message_size + sizeof(struct RadiotapHeader)
496                                         + sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader)
497                                         + sizeof(struct FragmentationHeader);
498         msgheader = GNUNET_malloc(size);
499         msgheader->size = pm->message_size + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader);
500         msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
501
502         radioHeader = (struct RadiotapHeader*) &msgheader[1];
503         getRadiotapHeader(radioHeader);
504
505         wlanheader = (struct IeeeHeader *) &radioHeader[1];
506         getWlanHeader(wlanheader);
507
508         bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
509   } else {
510           //remove message
511           GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
512                                                                   session->pending_messages_tail,
513                                                                   pm);
514           GNUNET_free(pm);
515
516   }
517
518
519
520
521
522   if (bytes < 1)
523     {
524       return;
525     }
526
527   //plugin->server_read_task =
528   //GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
529   //                                GNUNET_TIME_UNIT_FOREVER_REL,
530   //                                plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
531
532 }
533
534 /**
535  * If we have pending messages, ask the server to
536  * transmit them (schedule the respective tasks, etc.)
537  *
538  * @param Plugin env to get everything needed
539  */
540 static void
541 process_pending_messages (struct Plugin * plugin)
542 {
543   struct Sessionqueue * queue;
544   struct Session * session;
545
546   if (plugin->pending_Sessions == NULL)
547     return;
548
549   queue = plugin->pending_Sessions;
550   //contet should not be empty
551   GNUNET_assert(queue->content != NULL);
552
553   session = queue->content;
554   //pending sessions should have some msg
555   GNUNET_assert(session->pending_messages_head != NULL);
556
557   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
558   plugin->server_write_task
559     = GNUNET_SCHEDULER_add_write_file(plugin->env->sched,
560                                                                                         GNUNET_TIME_UNIT_FOREVER_REL,
561                                                                                         plugin->server_stdin_handle,
562                                            &do_transmit,
563                                            plugin);
564 }
565
566
567
568 /**
569  * Function that can be used by the transport service to transmit
570  * a message using the plugin.
571  *
572  * @param cls closure
573  * @param target who should receive this message
574  * @param priority how important is the message
575  * @param msgbuf the message to transmit
576  * @param msgbuf_size number of bytes in 'msgbuf'
577  * @param timeout when should we time out 
578  * @param session which session must be used (or NULL for "any")
579  * @param addr the address to use (can be NULL if the plugin
580  *                is "on its own" (i.e. re-use existing TCP connection))
581  * @param addrlen length of the address in bytes
582  * @param force_address GNUNET_YES if the plugin MUST use the given address,
583  *                otherwise the plugin may use other addresses or
584  *                existing connections (if available)
585  * @param cont continuation to call once the message has
586  *        been transmitted (or if the transport is ready
587  *        for the next transmission call; or if the
588  *        peer disconnected...)
589  * @param cont_cls closure for cont
590  * @return number of bytes used (on the physical network, with overheads);
591  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
592  *         and does NOT mean that the message was not transmitted (DV)
593  */
594 static ssize_t
595 wlan_plugin_send (void *cls,
596                   const struct GNUNET_PeerIdentity * target,
597                   const char *msgbuf,
598                   size_t msgbuf_size,
599                   unsigned int priority,
600                   struct GNUNET_TIME_Relative timeout,
601                   struct Session *session,
602                   const void *addr,
603                   size_t addrlen,
604                   int force_address,
605                   GNUNET_TRANSPORT_TransmitContinuation cont,
606                   void *cont_cls)
607 {
608   struct Plugin * plugin = cls;
609   struct PendingMessage * newmsg = NULL;
610
611   //check if msglen > 0
612   GNUNET_assert(msgbuf_size > 0);
613
614   //get session if needed
615   if (session == NULL) {
616           if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
617                   session = get_Session(plugin, addr);
618           } else {
619                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620                                         _("Wlan Address len %d is wrong\n"),
621                                          addrlen);
622                   return -1;
623           }
624   }
625
626   //TODO target "problem" not solved
627   session->target = *target;
628
629   //queue message:
630   //first queue session
631   queue_Session(plugin, session);
632
633   //queue message in session
634   newmsg = GNUNET_malloc(sizeof(struct PendingMessage) + msgbuf_size);
635   newmsg->msg = (const char*) &newmsg[1];
636   //copy msg to buffer, not fragmented / segmented yet
637   memcpy(&newmsg[1], msgbuf, msgbuf_size);
638   newmsg->transmit_cont = cont;
639   newmsg->transmit_cont_cls = cont_cls;
640   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
641   newmsg->message_pos = 0;
642   newmsg->message_size = msgbuf_size;
643   newmsg->next = NULL;
644
645   //check if queue is empty
646   struct PendingMessage * tailmsg;
647   tailmsg = session->pending_messages_tail;
648
649   //new tail is the new msg
650   session->pending_messages_tail = newmsg;
651   newmsg->prev = tailmsg;
652
653   //test if tail was not NULL (queue is empty)
654   if (tailmsg == NULL){
655           // head should be NULL too
656           GNUNET_assert(session->pending_messages_head == NULL);
657
658           session->pending_messages_head = newmsg;
659
660   } else {
661           //next at the tail should be NULL
662           GNUNET_assert(tailmsg->next == NULL);
663
664           //queue the msg
665           tailmsg->next = newmsg;
666   }
667
668   process_pending_messages(plugin);
669
670
671   //FIXME not the correct size
672   return msgbuf_size;
673
674 }
675
676
677
678 /**
679  * Function that can be used to force the plugin to disconnect
680  * from the given peer and cancel all previous transmissions
681  * (and their continuation).
682  *
683  * @param cls closure
684  * @param target peer from which to disconnect
685  */
686 static void
687 wlan_plugin_disconnect (void *cls,
688                             const struct GNUNET_PeerIdentity *target)
689 {
690   // struct Plugin *plugin = cls;
691   // FIXME
692 }
693
694
695 /**
696  * Convert the transports address to a nice, human-readable
697  * format.
698  *
699  * @param cls closure
700  * @param type name of the transport that generated the address
701  * @param addr one of the addresses of the host, NULL for the last address
702  *        the specific address format depends on the transport
703  * @param addrlen length of the address
704  * @param numeric should (IP) addresses be displayed in numeric form?
705  * @param timeout after how long should we give up?
706  * @param asc function to call on each string
707  * @param asc_cls closure for asc
708  */
709 static void
710 wlan_plugin_address_pretty_printer (void *cls,
711                                     const char *type,
712                                     const void *addr,
713                                     size_t addrlen,
714                                     int numeric,
715                                     struct GNUNET_TIME_Relative timeout,
716                                     GNUNET_TRANSPORT_AddressStringCallback
717                                     asc, void *asc_cls)
718 {
719   char ret[92];
720   const unsigned char * input;
721   
722   GNUNET_assert(cls !=NULL);
723   if (addrlen != 6)
724     {
725       /* invalid address (MAC addresses have 6 bytes) */
726       GNUNET_break (0);
727       asc (asc_cls, NULL);
728       return;
729     }
730   input = (const unsigned char*) addr;
731   GNUNET_snprintf (ret, 
732                    sizeof (ret),
733                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
734                    PROTOCOL_PREFIX, 
735                    input[0], input[1], input[2], input[3], input[4], input[5]);  
736   asc (asc_cls, ret);
737 }
738
739
740
741 /**
742  * Another peer has suggested an address for this
743  * peer and transport plugin.  Check that this could be a valid
744  * address.  If so, consider adding it to the list
745  * of addresses.
746  *
747  * @param cls closure
748  * @param addr pointer to the address
749  * @param addrlen length of addr
750  * @return GNUNET_OK if this is a plausible address for this peer
751  *         and transport
752  */
753
754
755 static int
756 wlan_plugin_address_suggested (void *cls,
757                                    const void *addr,
758                                    size_t addrlen)
759 {
760   /* struct Plugin *plugin = cls; */
761
762   /* check if the address is plausible; if so,
763      add it to our list! */
764
765   GNUNET_assert(cls !=NULL);
766
767   //Mac Adress has 6 bytes
768   if (addrlen == 6){
769     /* TODO check for bad addresses like milticast, broadcast, etc */
770     return GNUNET_OK;
771   } else {
772     return GNUNET_SYSERR;
773   }
774
775   return GNUNET_SYSERR;
776 }
777
778
779 /**
780  * Function called for a quick conversion of the binary address to
781  * a numeric address.  Note that the caller must not free the 
782  * address and that the next call to this function is allowed
783  * to override the address again.
784  *
785  * @param cls closure
786  * @param addr binary address
787  * @param addrlen length of the address
788  * @return string representing the same address 
789  */
790 static const char* 
791 wlan_plugin_address_to_string (void *cls,
792                                const void *addr,
793                                size_t addrlen)
794 {
795   char ret[92];
796   const unsigned char * input;
797   
798   GNUNET_assert(cls !=NULL);
799   if (addrlen != 6)
800     {
801       /* invalid address (MAC addresses have 6 bytes) */
802       GNUNET_break (0);
803       return NULL;
804     }
805   input = (const unsigned char*) addr;
806   GNUNET_snprintf (ret, 
807                    sizeof (ret),
808                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
809                    PROTOCOL_PREFIX, 
810                    input[0], input[1], input[2], input[3], input[4], input[5]);  
811   return GNUNET_strdup (ret);
812 }
813
814
815 #if 1
816 /**
817  * Function used for to process the data from the suid process
818  */
819 static void
820 wlan_process_helper (void *cls,
821                       void *client,
822                       const struct GNUNET_MessageHeader *hdr)
823 {
824   struct Plugin *plugin = cls;
825   if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
826     //TODO DATA
827   } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
828     //TODO ADV
829   } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
830     //TODO Control
831     if (hdr->size == 6){
832       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
833       plugin->env->notify_address (plugin->env->cls,
834                                       "wlan",
835                                       &plugin->mac_address, sizeof(plugin->mac_address),
836                                       GNUNET_TIME_UNIT_FOREVER_REL);
837     } else {
838       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
839     }
840
841
842   } else {
843     // TODO Wrong data?
844   }
845 }
846
847
848 static void
849 wlan_plugin_helper_read (void *cls,
850                          const struct GNUNET_SCHEDULER_TaskContext *tc)
851 {
852   struct Plugin *plugin = cls;
853   char mybuf[WLAN_MTU]; 
854   ssize_t bytes;
855
856   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
857     return;
858   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
859                                  mybuf, sizeof(mybuf));
860   if (bytes <= 0)
861     {
862 #if DEBUG_TCP_NAT
863       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
864                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
865 #endif
866       return;
867     }
868   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
869                             mybuf, bytes, 0, GNUNET_NO);
870
871 }
872
873
874 /**
875  * Start the gnunet-wlan-helper process.
876  *
877  * @param plugin the transport plugin
878  *
879  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
880  */
881 static int
882 wlan_transport_start_wlan_helper (struct Plugin *plugin)
883 {
884
885   plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
886   if (plugin->server_stdout == NULL)
887     return GNUNET_SYSERR;
888
889   plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
890     if (plugin->server_stdin == NULL)
891       return GNUNET_SYSERR;
892
893 #if DEBUG_TCP_NAT
894   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
895                    "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
896 #endif
897   /* Start the server process */
898   plugin->server_pid = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
899   if (plugin->server_pid == GNUNET_SYSERR)
900     {
901 #if DEBUG_TCP_NAT
902     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
903                      "Failed to start gnunet-wlan-helper process\n");
904 #endif
905       return GNUNET_SYSERR;
906     }
907   /* Close the write end of the read pipe */
908   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
909
910   /* Close the read end of the write pipe */
911   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
912
913   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
914   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
915
916   plugin->server_read_task =
917   GNUNET_SCHEDULER_add_read_file (plugin->env->sched,
918                                   GNUNET_TIME_UNIT_FOREVER_REL,
919                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
920   return GNUNET_YES;
921 }
922
923
924
925 #endif
926
927
928 /**
929  * Entry point for the plugin.
930  *
931  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
932  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
933  */
934 void *
935 gnunet_plugin_transport_wlan_init (void *cls)
936 {
937   struct GNUNET_SERVICE_Context *service;
938   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
939   struct GNUNET_TRANSPORT_PluginFunctions *api;
940   struct Plugin *plugin;
941
942   GNUNET_assert(cls !=NULL);
943
944   service = GNUNET_SERVICE_start ("transport-wlan", env->sched, env->cfg);
945         if (service == NULL){
946                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
947                            _("Failed to start service for `%s' transport plugin.\n"),
948                            "wlan");
949                 return NULL;
950         }
951
952   plugin = GNUNET_malloc (sizeof (struct Plugin));
953   plugin->env = env;
954
955   wlan_transport_start_wlan_helper(plugin);
956   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
957
958   //plugin->all_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
959   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
960
961   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
962   api->cls = plugin;
963   api->send = &wlan_plugin_send;
964   api->disconnect = &wlan_plugin_disconnect;
965   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
966   api->check_address = &wlan_plugin_address_suggested;
967   api->address_to_string = &wlan_plugin_address_to_string;
968
969   return api;
970 }
971
972
973 /**
974  * Exit point from the plugin.
975  */
976 void *
977 gnunet_plugin_transport_wlan_done (void *cls)
978 {
979   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
980   struct Plugin *plugin = api->cls;
981
982   GNUNET_assert(cls !=NULL);
983
984   GNUNET_free (plugin);
985   GNUNET_free (api);
986   return NULL;
987 }
988
989 /* end of plugin_transport_wlan.c */