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