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