e8d4d11c5bdd3e78db595e5378e176b86a4aca8f
[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_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
37
38 #define PROTOCOL_PREFIX "wlan"
39
40 /**
41  * Max size of packet from helper
42  */
43 #define WLAN_MTU 3000
44
45 /**
46  * Time until retransmission of a fragment in ms
47  */
48 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS 
49
50 #define FRAGMENT_QUEUE_SIZE 10
51
52 #define DEBUG_wlan GNUNET_YES
53
54 #define MESSAGE_LENGHT_UNKNOWN -1
55 #define NO_MESSAGE_OR_MESSAGE_FINISHED -2
56
57
58 /**
59  * After how long do we expire an address that we
60  * learned from another peer if it is not reconfirmed
61  * by anyone?
62  */
63 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
64
65 /**
66  * Initial handshake message for a session.
67  */
68 struct WelcomeMessage
69 {
70   /**
71    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
72    */
73   struct GNUNET_MessageHeader header;
74
75   /**
76    * Identit*mac_y of the node connecting (TCP client)
77    */
78   struct GNUNET_PeerIdentity clientIdentity;
79
80 };
81
82
83 /**
84  * Encapsulation of all of the state of the plugin.
85  */
86 struct Plugin
87 {
88   /**
89    * Our environment.
90    */
91   struct GNUNET_TRANSPORT_PluginEnvironment *env;
92
93   /**
94    * List of open sessions. head
95    */
96   struct Sessionqueue *sessions;
97
98   /**
99    * List of open sessions. tail
100    */
101   struct Sessionqueue *sessions_tail;
102
103   /**
104    * Number of sessions
105    */
106
107   int session_count;
108
109   /**
110    * encapsulation to the local wlan server prog
111    */
112
113   struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
114
115
116   /**
117    * stdout pipe handle for the gnunet-wlan-helper process
118    */
119   struct GNUNET_DISK_PipeHandle *server_stdout;
120
121   /**
122    * stdout file handle for the gnunet-wlan-helper process
123    */
124   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
125
126   /**
127    * stdin pipe handle for the gnunet-wlan-helper process
128    */
129   struct GNUNET_DISK_PipeHandle *server_stdin;
130
131   /**
132    * stdin file handle for the gnunet-wlan-helper process
133    */
134   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
135
136   /**
137    * ID of the gnunet-wlan-server std read task
138    */
139   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
140
141   /**
142    * ID of the gnunet-wlan-server std read task
143    */
144   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
145
146   /**
147    * ID of the delay task for writing
148    */
149   GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
150
151   /**
152    * The process id of the wlan process
153    */
154   struct GNUNET_OS_Process *server_proc;
155
156   /**
157    * The interface of the wlan card given to us by the user.
158    */
159   char *interface;
160
161   /**
162    * The mac_address of the wlan card given to us by the helper.
163    */
164   struct MacAddress mac_address;
165
166   /**
167    * Sessions currently pending for transmission
168    * to this peer, if any.
169    */
170   struct Sessionqueue * pending_Sessions;
171
172   /**
173     * Sessions currently pending for transmission
174     * to this peer (tail), if any.
175     */
176   struct Sessionqueue * pending_Sessions_tail;
177
178   /**
179    * number of pending sessions
180    */
181   unsigned int pendingsessions;
182
183   /**
184    * Messages in the fragmentation queue, head
185    */
186
187   struct FragmentMessage * pending_Fragment_Messages_head;
188
189   /**
190    * Messages in the fragmentation queue, tail
191    */
192
193   struct FragmentMessage * pending_Fragment_Messages_tail;
194
195   /**
196      * number of pending fragment message
197      */
198
199   unsigned int pending_fragment_messages;
200
201   /**
202    * time of the next "hello-beacon"
203    */
204
205   struct GNUNET_TIME_Absolute beacon_time;
206
207 };
208
209 struct Finish_send
210 {
211   struct Plugin * plugin;
212   char * msgheader;
213   struct GNUNET_MessageHeader * msgstart;
214   ssize_t size;
215 };
216
217 /**
218  * Queue of sessions, for the general session queue and the pending session queue
219  */
220
221 struct Sessionqueue
222 {
223         struct Sessionqueue * next;
224         struct Sessionqueue * prev;
225         struct Session * content;
226 };
227
228 /**
229  * Queue of ack received for messages send
230  */
231
232 struct AckQueue
233 {
234         struct AckQueue * next;
235         struct AckQueue * prev;
236         int fragment_num; //TODO change it to offset if better
237 };
238
239
240
241 /**
242  * Queue for the fragments received
243  */
244
245 struct RecQueue
246 {
247         struct RecQueue * next;
248         struct RecQueue * prev;
249         uint16_t num;
250         const char * msg;
251         uint16_t size;
252 };
253
254 /**
255  * Information kept for each message that is yet to
256  * be transmitted.
257  */
258 struct PendingMessage
259 {
260
261   /**
262    * The pending message
263    */
264   char *msg;
265
266   /**
267    * Continuation function to call once the message
268    * has been sent.  Can be NULL if there is no
269    * continuation to call.
270    */
271   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
272
273   /**
274    * Cls for transmit_cont
275    */
276   void * transmit_cont_cls;
277
278   /**
279    * Timeout value for the pending message.
280    */
281   struct GNUNET_TIME_Absolute timeout;
282
283   /**
284    * Size of the message
285    */
286   size_t message_size;
287
288 };
289
290 /**
291  * Session infos gathered from a messages
292  */
293
294 struct Session_light
295 {
296   /**
297    * the session this message belongs to
298    */
299   struct Session * session;
300   /**
301    * peer mac address
302    */
303   uint8_t addr[6];
304 };
305
306 /**
307  * Session handle for connections.
308  */
309 struct Session
310 {
311
312   /**
313    * API requirement.
314    */
315   struct SessionHeader header;
316
317   /**
318    * Pointer to the global plugin struct.
319    */
320   struct Plugin *plugin;
321
322   /**
323    * Message currently pending for transmission
324    * to this peer, if any.
325    */
326   struct PendingMessage *pending_message;
327
328   /**
329    * To whom are we talking to (set to our identity
330    * if we are still waiting for the welcome message)
331    */
332   struct GNUNET_PeerIdentity target;
333
334   /**
335    * encapsulation of the receive data
336    */
337   //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
338
339   /**
340    * offset of the next fragment for the receive_token, -1 means last message finished
341    */
342
343   //int rec_offset;
344
345   /**
346    * size of the message received,
347    * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
348    * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
349    */
350
351   int rec_size;
352
353   /**
354    * Sorted queue with the fragments received; head
355    */
356
357   struct RecQueue * frag_head;
358
359   /**
360    * Sorted queue with the fragments received; tail
361    */
362
363   struct RecQueue * frag_tail;
364
365   /**
366    * peer mac address
367    */
368   char addr[6];
369
370   /**
371    * Address of the other peer (either based on our 'connect'
372    * call or on our 'accept' call).
373    */
374   void *connect_addr;
375
376   /**
377    * Last activity on this connection.  Used to select preferred
378    * connection.
379    */
380   struct GNUNET_TIME_Absolute last_activity;
381
382   /**
383    * current number for message incoming, to distinguish between the messages
384    */
385   uint32_t message_id_in;
386
387   /**
388    * current number for message outgoing, to distinguish between the messages
389    */
390   uint32_t message_id_out;
391
392   /**
393    * does this session have a message in the fragment queue
394    */
395
396   int has_fragment;
397
398 };
399
400
401
402
403 struct FragmentMessage
404 {
405         /**
406          * Session this message belongs to
407          */
408
409         struct Session *session;
410
411         /**
412         * This is a doubly-linked list.
413         */
414         struct FragmentMessage *next;
415
416         /**
417         * This is a doubly-linked list.
418         */
419         struct FragmentMessage *prev;
420
421         /**
422         * The pending message
423         */
424         char *msg;
425
426         /**
427         * Timeout value for the pending message.
428         */
429         struct GNUNET_TIME_Absolute timeout;
430
431         /**
432         * Timeout value for the pending fragments.
433         * Stores the time when the next msg fragment ack has to be received
434         */
435         struct GNUNET_TIME_Absolute next_ack;
436
437         /**
438         * Sorted queue with the acks received for fragments; head
439         */
440
441         struct AckQueue * head;
442
443         /**
444         * Sorted queue with the acks received for fragments; tail
445         */
446
447         struct AckQueue * tail;
448
449         /**
450         * Size of the message
451         */
452         size_t message_size;
453
454         /**
455         * pos / next fragment number in the message, for fragmentation/segmentation,
456         * some acks can be missing but there is still time
457         */
458         uint32_t message_pos;
459
460 };
461
462 /**
463  * Header for messages which need fragmentation
464  */
465 struct WlanHeader
466 {
467
468   struct GNUNET_MessageHeader header;
469
470   /**
471    * checksum/error correction
472    */
473   uint32_t crc GNUNET_PACKED;
474
475   /**
476    * To whom are we talking to (set to our identity
477    * if we are still waiting for the welcome message)
478    */
479   struct GNUNET_PeerIdentity target;
480
481   // followed by payload
482
483 };
484
485 /**
486  * Header for messages which need fragmentation
487  */
488 struct FragmentationHeader
489 {
490
491   struct GNUNET_MessageHeader header;
492
493   /**
494    * To whom are we talking to (set to our identity
495    * if we are still waiting for the welcome message)
496    */
497   // struct GNUNET_PeerIdentity target GNUNET_PACKED;
498
499   /**
500    * ID of message, to distinguish between the messages, picked randomly.
501    */
502   uint32_t message_id GNUNET_PACKED;
503
504   /**
505    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
506    */
507   uint16_t fragment_off_or_num GNUNET_PACKED;
508
509   /**
510    * CRC of fragment (for error checking)
511    */
512   uint16_t message_crc GNUNET_PACKED;
513
514   /**
515    * Flags
516    * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
517    * // 0x2 has data (not only ack)
518    * // 0x4 last fragment of message
519    * // 0x8 new message
520    */
521   //  uint32_t flags GNUNET_PACKED;
522
523   /**
524    * checksum/error correction
525    */
526   // uint32_t crc GNUNET_PACKED;
527
528   // followed by payload unless ACK
529
530 };
531
532 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
533
534 int
535 getRadiotapHeader(struct RadiotapHeader * Header);
536
537 int
538 getWlanHeader(struct IeeeHeader * Header);
539
540 static int
541 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
542
543 uint16_t
544 getcrc16(const char *msgbuf, size_t msgbuf_size);
545
546 static void
547 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
548
549 static void
550 check_fragment_queue(struct Plugin * plugin);
551
552 uint32_t
553 getcrc32(const char *msgbuf, size_t msgbuf_size);
554
555 static void
556 free_rec_frag_queue(struct Session * session);
557
558 static void
559 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr);
560
561 static void
562 wlan_process_helper (void *cls,
563                       void *client,
564                       const struct GNUNET_MessageHeader *hdr);
565
566 static void
567 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
568
569 /**
570  * get the next message number, at the moment just a random one
571  * @return returns the next valid message-number for sending packets
572  */
573 uint32_t
574 get_next_message_id()
575 {
576   return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
577 }
578
579 /**
580  * start next message number generator
581  * (not necessary at the moment)
582  */
583 void
584 start_next_message_id()
585 {
586   //GNUNET_CRYPTO_random_init;
587 }
588
589 /**
590  * search for a session with the addr
591  *
592  * @param plugin pointer to the plugin struct
593  * @param addr pointer to the mac address of the peer
594  * @return returns the session
595  */
596
597 static struct Session *
598 search_session(struct Plugin *plugin, const uint8_t * addr)
599 {
600   struct Sessionqueue * queue = plugin->sessions;
601   struct Sessionqueue * lastitem = NULL;
602
603   //just look at all the session for the needed one
604   while (queue != NULL)
605     {
606       // content is never NULL
607       GNUNET_assert (queue->content != NULL);
608       char * addr2 = queue->content->addr;
609       if (memcmp(addr, addr2, 6) == 0)
610         {
611           //sesion found
612           return queue->content;
613         }
614       // try next
615       lastitem = queue;
616       queue = queue->next;
617     }
618   return NULL;
619 }
620
621 /**
622  * create a new session
623  *
624  * @param plugin pointer to the plugin struct
625  * @param addr pointer to the mac address of the peer
626  * @return returns the session
627  */
628
629 static struct Session *
630 create_session(struct Plugin *plugin,const uint8_t * addr)
631 {
632   struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
633
634   GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
635
636   queue->content = GNUNET_malloc (sizeof (struct Session));
637   queue->content->plugin = plugin;
638   memcpy(queue->content->addr, addr, 6);
639   queue->content->message_id_out = get_next_message_id();
640   queue->content->has_fragment = 0;
641   queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
642
643   plugin->session_count++;
644   return queue->content;
645 }
646
647 /**
648  * get Session from address, create if no session exists
649  *
650  * @param plugin pointer to the plugin struct
651  * @param addr pointer to the mac address of the peer
652  * @return returns the session
653  */
654 //TODO add other possibilities to find the right session (are there other?)
655 static struct Session *
656 get_Session(struct Plugin *plugin, const uint8_t * addr)
657 {
658   struct Session * session = search_session(plugin, addr);
659   if (session != NULL)
660     {
661       return session;
662     }
663   // new session
664   return create_session(plugin, addr);
665
666   /* -- not needed, layer above already has it--
667    //queue welcome message for new sessions, not realy needed
668    //struct WelcomeMessage welcome;
669    struct PendingMessage *pm;
670    pm = GNUNET_malloc (sizeof (struct PendingMessage));
671    pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
672    pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
673    //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
674    //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
675    //welcome.clientIdentity = *plugin->env->my_identity;
676    memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
677    pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
678    queue->content->pending_message = pm;
679    plugin->pendingsessions ++;
680    GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
681
682    check_fragment_queue(plugin);
683    */
684 }
685
686 /**
687  * Queue the session to send data
688  */
689 //TODO doxigen
690 static void
691 queue_Session (struct Plugin *plugin,
692                 struct Session * session)
693 {
694         struct Sessionqueue * queue = plugin->pending_Sessions;
695         struct Sessionqueue * lastitem = NULL;
696
697         while (queue != NULL){
698                 // content is never NULL
699                 GNUNET_assert (queue->content == NULL);
700                 // is session already in queue?
701                 if (session == queue->content){
702                         return;
703                 }
704                 // try next
705                 lastitem = queue;
706                 queue = queue->next;
707         }
708
709         // Session is not in the queue
710
711         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
712         queue->content = session;
713
714         //insert at the tail
715         GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
716                         plugin->pending_Sessions_tail,
717                         plugin->pending_Sessions_tail, queue);
718         plugin->pendingsessions ++;
719
720 }
721
722 //TODO doxigen
723 static void
724 free_acks (struct FragmentMessage * fm){
725         struct AckQueue * fq;
726         while (fm->head != NULL){
727                 fq = fm->head;
728                 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
729                 GNUNET_free(fq);
730         }
731         //needed?
732         fm->head = NULL;
733         fm->tail = NULL;
734 }
735
736 //TODO doxigen
737 /**
738  * Function to schedule the write task, executed after a delay
739  */
740 static void
741 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
742 {
743   struct Plugin * plugin = cls;
744   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
745
746   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
747     return;
748
749   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
750   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
751     {
752       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
753           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
754           &do_transmit, plugin);
755     }
756 }
757
758 //TODO doxigen
759 /**
760  * Function to calculate the time of the next periodic "hello-beacon"
761  */
762 static void
763 set_next_beacon_time(struct Plugin * const plugin)
764 {
765   //under 10 known peers: once a second
766   if (plugin->session_count < 10)
767     {
768       plugin->beacon_time = GNUNET_TIME_absolute_add(
769           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
770     }
771   //under 30 known peers: every 10 seconds
772   else if (plugin->session_count < 30)
773     {
774       plugin->beacon_time = GNUNET_TIME_absolute_add(
775           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
776               GNUNET_TIME_UNIT_SECONDS, 10));
777     }
778   //over 30 known peers: once a minute
779   else
780     {
781       plugin->beacon_time = GNUNET_TIME_absolute_add(
782           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
783     }
784 }
785
786
787 //TODO doxigen
788 struct GNUNET_TIME_Relative
789 get_next_frag_timeout(struct FragmentMessage * fm)
790 {
791   return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
792       fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
793 }
794
795 //TODO doxigen
796 /**
797  * Function to get the timeout value for acks for this session
798  */
799
800 struct GNUNET_TIME_Relative
801 get_ack_timeout (struct FragmentMessage * fm){
802         return FRAGMENT_TIMEOUT;
803 }
804
805
806 /**
807  * Function to set the timer for the next timeout of the fragment queue
808  * @param plugin the handle to the plugin struct
809  */
810 static void
811 check_next_fragment_timeout(struct Plugin * const plugin)
812 {
813   struct FragmentMessage * fm;
814   struct GNUNET_TIME_Relative next_send;
815
816   next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
817
818   //cancel old task
819   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
820     {
821       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
822     }
823   fm = plugin->pending_Fragment_Messages_head;
824
825   GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
826
827   //check if there are some fragments in the queue
828   if (fm != NULL)
829     {
830       next_send
831           = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
832     }
833   plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
834       &delay_fragment_task, plugin);
835 }
836
837
838
839 //TODO doxigen
840 /**
841  * Function to get the next queued Session, removes the session from the queue
842  */
843
844 static struct Session *
845 get_next_queue_Session (struct Plugin * plugin){
846         struct Session * session;
847         struct Sessionqueue * sessionqueue;
848         struct Sessionqueue * sessionqueue_alt;
849         struct PendingMessage * pm;
850         sessionqueue = plugin->pending_Sessions;
851         while (sessionqueue != NULL){
852                 session = sessionqueue->content;
853                 pm = session->pending_message;
854
855                 //check for message timeout
856                 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
857                         //check if session has no message in the fragment queue
858                         if (! session->has_fragment){
859                                 plugin->pendingsessions --;
860                                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
861                                                 plugin->pending_Sessions_tail, sessionqueue);
862                                 GNUNET_free(sessionqueue);
863
864                                 return session;
865                         } else {
866                                 sessionqueue = sessionqueue->next;
867                         }
868                 } else {
869
870                         session->pending_message = NULL;
871                         //call the cont func that it did not work
872                         if (pm->transmit_cont != NULL)
873                           pm->transmit_cont (pm->transmit_cont_cls,
874                                                 &(session->target), GNUNET_SYSERR);
875                         GNUNET_free(pm->msg);
876                         GNUNET_free(pm);
877
878                         sessionqueue_alt = sessionqueue;
879                         sessionqueue = sessionqueue->next;
880                         plugin->pendingsessions --;
881                         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
882                                         plugin->pending_Sessions_tail, sessionqueue_alt);
883
884                         GNUNET_free(sessionqueue_alt);
885
886                 }
887
888
889         }
890         return NULL;
891 }
892
893
894 /**
895  * Function to sort the message into the message fragment queue
896  * @prarm plugin the plugin struct
897  * @param message to sort into the queue
898  */
899 static void
900 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
901         struct FragmentMessage * fm2;
902         //sort into the list at the right position
903
904         fm2 = plugin->pending_Fragment_Messages_head;
905
906         while (fm2 != NULL){
907                 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
908                         break;
909                 } else {
910                         fm2 = fm2->next;
911                 }
912         }
913
914         GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
915                         plugin->pending_Fragment_Messages_tail,fm2,fm);
916 }
917
918 /**
919  * frees the space of a message in the fragment queue (send queue)
920  * @param plugin the plugin struct
921  * @param fm message to free
922  */
923 static void
924 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
925 {
926   if (fm != NULL)
927     {
928       free_acks(fm);
929       GNUNET_free_non_null(fm->msg);
930       GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
931           plugin->pending_Fragment_Messages_tail, fm);
932       GNUNET_free(fm);
933       plugin->pending_fragment_messages --;
934       check_fragment_queue(plugin);
935     }
936 }
937
938 /**
939  * Function to check if there is some space in the fragment queue
940  * inserts a message if space is available
941  * @param plugin the plugin struct
942  */
943
944 static void
945 check_fragment_queue (struct Plugin * plugin){
946         struct Session * session;
947         struct FragmentMessage * fm;
948
949         struct PendingMessage * pm;
950
951         if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
952                 session = get_next_queue_Session(plugin);
953                 if (session != NULL){
954                         pm = session->pending_message;
955                         session->pending_message = NULL;
956                         session->has_fragment = 1;
957                         GNUNET_assert(pm != NULL);
958
959                         fm = GNUNET_malloc(sizeof(struct FragmentMessage));
960                         fm->message_size = pm->message_size;
961                         fm->msg = pm->msg;
962                         fm->session = session;
963                         fm->timeout.abs_value = pm->timeout.abs_value;
964                         fm->message_pos = 0;
965                         fm->next_ack = GNUNET_TIME_absolute_get();
966
967                         if (pm->transmit_cont != NULL)
968                                   pm->transmit_cont (pm->transmit_cont_cls,
969                                                         &(session->target), GNUNET_OK);
970                         GNUNET_free(pm);
971
972                         sort_fragment_into_queue(plugin,fm);
973                         plugin->pending_fragment_messages ++;
974
975                         //generate new message id
976                         session->message_id_out = get_next_message_id();
977
978                         //check if timeout changed
979                         check_next_fragment_timeout(plugin);
980                 }
981         }
982 }
983
984 /**
985  * Funktion to check if all fragments where send and the acks received
986  * frees the space if finished
987  * @param plugin the plugin struct
988  * @param fm the message to check
989  */
990 static void
991 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
992   struct AckQueue * ack;
993   int counter = 0;
994
995   if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
996       * fm->tail->fragment_num)
997     {
998       ack = fm->head;
999       counter = 0;
1000       //check if all acks are present
1001       while (ack != NULL)
1002         {
1003           if (counter == ack->fragment_num)
1004             {
1005               counter ++;
1006               ack = ack->next;
1007             } else {
1008               //ack is missing
1009               return;
1010             }
1011         }
1012       fm->session->has_fragment = 0;
1013       free_fragment_message(plugin, fm);
1014
1015
1016     }
1017 }
1018
1019 /**
1020  * Function called when wlan helper is ready to get some data
1021  *
1022  * @param cls closure
1023  * @param tc GNUNET_SCHEDULER_TaskContext
1024  */
1025
1026 static void
1027 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1028 {
1029
1030   struct Plugin * plugin = cls;
1031   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1032
1033   ssize_t bytes;
1034
1035   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1036     return;
1037
1038   struct Session * session = NULL;
1039   struct FragmentMessage * fm = NULL;
1040   struct IeeeHeader * ieeewlanheader = NULL;
1041   struct RadiotapHeader * radioHeader = NULL;
1042   struct GNUNET_MessageHeader * msgheader = NULL;
1043   struct GNUNET_MessageHeader * msgheader2 = NULL;
1044   struct FragmentationHeader fragheader;
1045   struct FragmentationHeader * fragheaderptr = NULL;
1046   struct Finish_send * finish = NULL;
1047   uint16_t size = 0;
1048   const char * copystart = NULL;
1049   uint16_t copysize = 0;
1050   uint copyoffset = 0;
1051   struct AckQueue * akt = NULL;
1052
1053   //test if a "hello-beacon" has to be send
1054   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1055     {
1056       //check if the message is not to big
1057       GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1058               *(plugin->env->our_hello)) <= WLAN_MTU);
1059       size = sizeof(struct GNUNET_MessageHeader)
1060           + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1061           + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1062           *(plugin->env->our_hello));
1063
1064       msgheader = GNUNET_malloc(size);
1065       msgheader->size = htons(size);
1066       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1067
1068       radioHeader = (struct RadiotapHeader *) &msgheader[1];
1069       getRadiotapHeader(radioHeader);
1070
1071       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1072       getWlanHeader(ieeewlanheader);
1073
1074       msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1075       msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1076           + sizeof(struct GNUNET_MessageHeader));
1077       msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1078
1079       memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1080           *(plugin->env->our_hello)));
1081
1082       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1083           size);
1084       if (bytes == GNUNET_SYSERR)
1085         {
1086           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1087               _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1088               errno, strerror(errno));
1089
1090         }
1091       GNUNET_assert(bytes != GNUNET_SYSERR);
1092       GNUNET_assert(bytes == size);
1093
1094       GNUNET_free(msgheader);
1095
1096       set_next_beacon_time(plugin);
1097       check_next_fragment_timeout(plugin);
1098
1099       return;
1100
1101     }
1102
1103   fm = plugin->pending_Fragment_Messages_head;
1104   GNUNET_assert(fm != NULL);
1105   session = fm->session;
1106   GNUNET_assert(session != NULL);
1107
1108   // test if message timed out
1109   if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1110     {
1111       free_acks(fm);
1112       GNUNET_assert(plugin->pending_fragment_messages > 0);
1113       plugin->pending_fragment_messages--;
1114       GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1115           plugin->pending_Fragment_Messages_tail, fm);
1116
1117       GNUNET_free(fm->msg);
1118
1119       GNUNET_free(fm);
1120       check_fragment_queue(plugin);
1121     }
1122   else
1123     {
1124
1125       if (fm->message_size > WLAN_MTU)
1126         {
1127           size += sizeof(struct FragmentationHeader);
1128           // check/set for retransmission
1129           if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0)
1130             {
1131
1132               // be positive and try again later :-D
1133               fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(
1134                   fm));
1135               // find first missing fragment
1136               akt = fm->head;
1137               fm->message_pos = 0;
1138
1139               //test if ack 0 was already received
1140               while (akt != NULL)
1141                 {
1142                   //if fragment is present, take next
1143                   if (akt->fragment_num == fm->message_pos)
1144                     {
1145                       fm->message_pos++;
1146                     }
1147                   //next ack is bigger then the fragment number
1148                   //in case there is something like this: (acks) 1, 2, 5, 6, ...
1149                   //and we send 3 again, the next number should be 4
1150                   else if (akt->fragment_num > fm->message_pos)
1151                     {
1152                       break;
1153                     }
1154
1155                   akt = akt->next;
1156
1157                 }
1158
1159             }
1160
1161           copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1162               * fm->message_pos;
1163           fragheader.fragment_off_or_num = htons(fm->message_pos);
1164           fragheader.message_id = htonl(session->message_id_out);
1165
1166           // start should be smaller then the packet size
1167           GNUNET_assert(copyoffset < fm->message_size);
1168           copystart = fm->msg + copyoffset;
1169
1170           //size of the fragment is either the MTU - overhead
1171           //or the missing part of the message in case this is the last fragment
1172           copysize = GNUNET_MIN(fm->message_size - copyoffset,
1173               WLAN_MTU - sizeof(struct FragmentationHeader));
1174           fragheader.header.size = htons(copysize
1175               + sizeof(struct FragmentationHeader));
1176           fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1177
1178           //get the next missing fragment
1179           akt = fm->head;
1180           fm->message_pos++;
1181
1182           //test if ack was already received
1183           while (akt != NULL)
1184             {
1185               //if fragment is present, take next
1186               if (akt->fragment_num == fm->message_pos)
1187                 {
1188                   fm->message_pos++;
1189                 }
1190               //next ack is bigger then the fragment number
1191               //in case there is something like this: (acks) 1, 2, 5, 6, ...
1192               //and we send 3 again, the next number should be 4
1193               else if (akt->fragment_num > fm->message_pos)
1194                 {
1195                   break;
1196                 }
1197
1198               akt = akt->next;
1199             }
1200         }
1201       else
1202         {
1203           // there is no need to split
1204           copystart = fm->msg;
1205           copysize = fm->message_size;
1206         }
1207
1208       size += copysize;
1209       size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1210           + sizeof(struct GNUNET_MessageHeader);
1211       msgheader = GNUNET_malloc(size);
1212       msgheader->size = htons(size);
1213       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1214
1215       radioHeader = (struct RadiotapHeader*) &msgheader[1];
1216       getRadiotapHeader(radioHeader);
1217
1218       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1219       getWlanHeader(ieeewlanheader);
1220
1221       //could be faster if content is just send and not copyed before
1222       //fragmentheader is needed
1223       if (fm->message_size > WLAN_MTU)
1224         {
1225           fragheader.message_crc = htons(getcrc16(copystart, copysize));
1226           memcpy(&ieeewlanheader[1], &fragheader,
1227               sizeof(struct FragmentationHeader));
1228           fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1229           memcpy(&fragheaderptr[1], copystart, copysize);
1230         }
1231       else
1232         {
1233           memcpy(&ieeewlanheader[1], copystart, copysize);
1234         }
1235
1236       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1237       if (bytes == GNUNET_SYSERR){
1238         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1239             _("Error writing to wlan healper. errno == %d, ERROR: %s\n"), errno, strerror(errno) );
1240
1241       }
1242       GNUNET_assert(bytes != GNUNET_SYSERR);
1243
1244       if (bytes != size)
1245         {
1246           finish = GNUNET_malloc(sizeof( struct Finish_send));
1247           finish->plugin = plugin;
1248           finish->msgheader = (char * ) msgheader + bytes;
1249           finish->size = size - bytes;
1250           finish->msgstart = msgheader;
1251
1252           GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1253
1254           plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1255               GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1256               &finish_sending, finish);
1257
1258         }
1259       else
1260         {
1261           GNUNET_assert(bytes == size);
1262
1263           GNUNET_free(msgheader);
1264           check_next_fragment_timeout(plugin);
1265         }
1266
1267       //check if this was the last fragment of this message, if true then queue at the end of the list
1268       if (copysize + copyoffset >= fm->message_size)
1269         {
1270           GNUNET_assert(copysize + copyoffset == fm->message_size);
1271
1272           GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1273               plugin->pending_Fragment_Messages_tail, fm);
1274
1275           GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1276               plugin->pending_Fragment_Messages_tail, fm);
1277           // if fragments have opimized timeouts
1278           //sort_fragment_into_queue(plugin,fm);
1279
1280         }
1281
1282     }
1283 }
1284
1285
1286 static void
1287 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1288 {
1289   struct Finish_send * finish;
1290   struct Plugin * plugin;
1291   ssize_t bytes;
1292
1293   finish = cls;
1294   plugin = finish->plugin;
1295
1296   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1297
1298   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, finish->msgheader, finish->size);
1299   GNUNET_assert(bytes != GNUNET_SYSERR);
1300
1301   GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1302   if (bytes != finish->size)
1303     {
1304
1305       finish->plugin = plugin;
1306       finish->msgheader = finish->msgheader + bytes;
1307       finish->size = finish->size - bytes;
1308       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1309           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1310           &finish_sending, finish);
1311     }
1312   else
1313     {
1314       GNUNET_free(finish->msgstart);
1315       GNUNET_free(finish);
1316       check_next_fragment_timeout(plugin);
1317     }
1318
1319 }
1320
1321 int
1322 getRadiotapHeader(struct RadiotapHeader * Header){
1323   return GNUNET_YES;
1324 };
1325
1326 int
1327 getWlanHeader(struct IeeeHeader * Header){
1328
1329   return GNUNET_YES;
1330 }
1331
1332
1333 /**
1334  * 32bit CRC
1335  *
1336  * @param msgbuf pointer tor the data
1337  * @param msgbuf_size size of the data
1338  *
1339  * @return 32bit crc value
1340  */
1341
1342 uint32_t
1343 getcrc32 (const char *msgbuf,
1344                   size_t msgbuf_size){
1345         //TODO calc some crc
1346         return 0;
1347 }
1348
1349 /**
1350  * 16bit CRC
1351  *
1352  * @param msgbuf pointer tor the data
1353  * @param msgbuf_size size of the data
1354  *
1355  * @return 16bit crc value
1356  */
1357
1358 uint16_t
1359 getcrc16 (const char *msgbuf,
1360                   size_t msgbuf_size){
1361         //TODO calc some crc
1362         return 0;
1363 }
1364
1365 /**
1366  * Function that can be used by the transport service to transmit
1367  * a message using the plugin.
1368  *
1369  * @param cls closure
1370  * @param target who should receive this message
1371  * @param priority how important is the message
1372  * @param msgbuf the message to transmit
1373  * @param msgbuf_size number of bytes in 'msgbuf'
1374  * @param timeout when should we time out 
1375  * @param session which session must be used (or NULL for "any")
1376  * @param addr the address to use (can be NULL if the plugin
1377  *                is "on its own" (i.e. re-use existing TCP connection))
1378  * @param addrlen length of the address in bytes
1379  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1380  *                otherwise the plugin may use other addresses or
1381  *                existing connections (if available)
1382  * @param cont continuation to call once the message has
1383  *        been transmitted (or if the transport is ready
1384  *        for the next transmission call; or if the
1385  *        peer disconnected...)
1386  * @param cont_cls closure for cont
1387  * @return number of bytes used (on the physical network, with overheads);
1388  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1389  *         and does NOT mean that the message was not transmitted (DV)
1390  */
1391 static ssize_t
1392 wlan_plugin_send (void *cls,
1393                   const struct GNUNET_PeerIdentity * target,
1394                   const char *msgbuf,
1395                   size_t msgbuf_size,
1396                   unsigned int priority,
1397                   struct GNUNET_TIME_Relative timeout,
1398                   struct Session *session,
1399                   const void *addr,
1400                   size_t addrlen,
1401                   int force_address,
1402                   GNUNET_TRANSPORT_TransmitContinuation cont,
1403                   void *cont_cls)
1404 {
1405   struct Plugin * plugin = cls;
1406   struct PendingMessage * newmsg = NULL;
1407   struct WlanHeader * wlanheader = NULL;
1408   //check if msglen > 0
1409   GNUNET_assert(msgbuf_size > 0);
1410
1411   //get session if needed
1412   if (session == NULL)
1413     {
1414       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1415         {
1416           session = get_Session(plugin, addr);
1417         }
1418       else
1419         {
1420           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1421               _("Wlan Address len %d is wrong\n"), addrlen);
1422           return -1;
1423         }
1424     }
1425
1426   //TODO target "problem" not solved
1427   session->target = *target;
1428
1429   //queue message:
1430   //first queue session
1431   queue_Session(plugin, session);
1432
1433   //queue message in session
1434   //test if there is no other message in the "queue"
1435   GNUNET_assert (session->pending_message == NULL);
1436
1437   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1438   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1439   wlanheader = (struct WlanHeader *) newmsg->msg;
1440   //copy msg to buffer, not fragmented / segmented yet, but with message header
1441   wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1442   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1443   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1444   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1445   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1446   newmsg->transmit_cont = cont;
1447   newmsg->transmit_cont_cls = cont_cls;
1448   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1449   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1450
1451   session->pending_message = newmsg;
1452
1453   check_fragment_queue(plugin);
1454   //FIXME not the correct size
1455   return msgbuf_size;
1456
1457 }
1458
1459 //TODO doxigen
1460 static struct FragmentMessage *
1461 get_fragment_message_from_session(struct Session * session)
1462 {
1463   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1464   while (fm != NULL)
1465     {
1466       if (fm->session == session)
1467         {
1468           return fm;
1469         }
1470       fm = fm->next;
1471     }
1472   return NULL;
1473 }
1474
1475 /**
1476  * Function that can be used to force the plugin to disconnect
1477  * from the given peer and cancel all previous transmissions
1478  * (and their continuation).
1479  *
1480  * @param cls closure
1481  * @param target peer from which to disconnect
1482  */
1483 static void
1484 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1485 {
1486   struct Plugin *plugin = cls;
1487   struct Sessionqueue * queue = plugin->sessions;
1488   struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1489   struct PendingMessage * pm = NULL;
1490   struct FragmentMessage * fm;
1491
1492   // just look at all the session for the needed one
1493   while (queue != NULL)
1494     {
1495       // content is never NULL
1496       GNUNET_assert (queue->content != NULL);
1497       if (memcmp(target, &(queue->content->target),
1498           sizeof(struct GNUNET_PeerIdentity)) == 0)
1499         {
1500           //session found
1501           //is this session pending for send
1502           while (pendingsession != NULL)
1503             {
1504               if (pendingsession->content == queue->content)
1505                 {
1506                   plugin->pendingsessions --;
1507                   GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1508                       plugin->pending_Sessions_tail, pendingsession);
1509                   GNUNET_free(pendingsession);
1510                   break;
1511                 }
1512               pendingsession = pendingsession->next;
1513             }
1514
1515           //is something of this session in the fragment queue?
1516           fm = get_fragment_message_from_session(queue->content);
1517           free_fragment_message(plugin,fm);
1518
1519           //dispose all received fragments
1520           free_rec_frag_queue(queue->content);
1521
1522           // remove PendingMessage
1523           pm = queue->content->pending_message;
1524           GNUNET_free(pm->msg);
1525           GNUNET_free(pm);
1526
1527           GNUNET_free(queue->content);
1528           GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1529           GNUNET_free(queue);
1530           plugin->session_count --;
1531
1532           return;
1533         }
1534       // try next
1535       queue = queue->next;
1536     }
1537 }
1538
1539
1540 /**
1541  * Convert the transports address to a nice, human-readable
1542  * format.
1543  *
1544  * @param cls closure
1545  * @param type name of the transport that generated the address
1546  * @param addr one of the addresses of the host, NULL for the last address
1547  *        the specific address format depends on the transport
1548  * @param addrlen length of the address
1549  * @param numeric should (IP) addresses be displayed in numeric form?
1550  * @param timeout after how long should we give up?
1551  * @param asc function to call on each string
1552  * @param asc_cls closure for asc
1553  */
1554 static void
1555 wlan_plugin_address_pretty_printer (void *cls,
1556                                     const char *type,
1557                                     const void *addr,
1558                                     size_t addrlen,
1559                                     int numeric,
1560                                     struct GNUNET_TIME_Relative timeout,
1561                                     GNUNET_TRANSPORT_AddressStringCallback
1562                                     asc, void *asc_cls)
1563 {
1564   char ret[92];
1565   const unsigned char * input;
1566   
1567   GNUNET_assert(cls !=NULL);
1568   if (addrlen != 6)
1569     {
1570       /* invalid address (MAC addresses have 6 bytes) */
1571       GNUNET_break (0);
1572       asc (asc_cls, NULL);
1573       return;
1574     }
1575   input = (const unsigned char*) addr;
1576   GNUNET_snprintf (ret, 
1577                    sizeof (ret),
1578                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1579                    PROTOCOL_PREFIX, 
1580                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1581   asc (asc_cls, ret);
1582 }
1583
1584
1585
1586 /**
1587  * Another peer has suggested an address for this
1588  * peer and transport plugin.  Check that this could be a valid
1589  * address.  If so, consider adding it to the list
1590  * of addresses.
1591  *
1592  * @param cls closure
1593  * @param addr pointer to the address
1594  * @param addrlen length of addr
1595  * @return GNUNET_OK if this is a plausible address for this peer
1596  *         and transport
1597  */
1598
1599
1600 static int
1601 wlan_plugin_address_suggested (void *cls,
1602                                    const void *addr,
1603                                    size_t addrlen)
1604 {
1605   //struct Plugin *plugin = cls;
1606
1607   /* check if the address is plausible; if so,
1608      add it to our list! */
1609
1610   GNUNET_assert(cls !=NULL);
1611   //FIXME mitm is not checked
1612   //Mac Adress has 6 bytes
1613   if (addrlen == 6){
1614     /* TODO check for bad addresses like milticast, broadcast, etc */
1615     return GNUNET_OK;
1616   } else {
1617     return GNUNET_SYSERR;
1618   }
1619
1620   return GNUNET_SYSERR;
1621 }
1622
1623
1624 /**
1625  * Function called for a quick conversion of the binary address to
1626  * a numeric address.  Note that the caller must not free the 
1627  * address and that the next call to this function is allowed
1628  * to override the address again.
1629  *
1630  * @param cls closure
1631  * @param addr binary address
1632  * @param addrlen length of the address
1633  * @return string representing the same address 
1634  */
1635 static const char* 
1636 wlan_plugin_address_to_string (void *cls,
1637                                const void *addr,
1638                                size_t addrlen)
1639 {
1640   char ret[92];
1641   const unsigned char * input;
1642   
1643   GNUNET_assert(cls !=NULL);
1644   if (addrlen != 6)
1645     {
1646       /* invalid address (MAC addresses have 6 bytes) */
1647       GNUNET_break (0);
1648       return NULL;
1649     }
1650   input = (const unsigned char*) addr;
1651   GNUNET_snprintf (ret, 
1652                    sizeof (ret),
1653                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1654                    PROTOCOL_PREFIX, 
1655                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1656   return GNUNET_strdup (ret);
1657 }
1658
1659 /**
1660  * Function to test if fragment number already exists in the fragments received
1661  *
1662  * @param session session the fragment belongs to
1663  * @param fh Fragmentheader of the fragment
1664  * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
1665  */
1666
1667 static const int
1668 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1669 {
1670   struct RecQueue * rec_queue = session->frag_head;
1671   while (rec_queue != NULL)
1672     {
1673       if (rec_queue->num == fh->fragment_off_or_num)
1674         {
1675           return GNUNET_YES;
1676         }
1677       rec_queue = rec_queue->next;
1678
1679     }
1680   return GNUNET_NO;
1681 }
1682
1683 /**
1684  * Function to insert a fragment in a queue of a session
1685  * @param session session the fragment belongs to
1686  * @param rec_queue fragment to add
1687  */
1688
1689 static void
1690 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1691 {
1692   struct RecQueue * rec_queue2 = session->frag_head;
1693   struct WlanHeader * wlanheader = NULL;
1694   //first received fragment of message
1695   if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1696     {
1697       session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1698     }
1699   //this is the first fragment of the message (fragment id 0)
1700   if (rec_queue->num == 0)
1701     {
1702       wlanheader = (struct WlanHeader *) rec_queue->msg;
1703       session->rec_size = wlanheader->header.size;
1704     }
1705
1706   //sort into list
1707   while (rec_queue2 != NULL)
1708     {
1709       if (rec_queue2->num > rec_queue->num)
1710         {
1711           //next element number is grater than the current num
1712           GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1713           return;
1714         }
1715       rec_queue = rec_queue->next;
1716     }
1717   //no element has a grater number
1718   GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1719 }
1720
1721 /**
1722  * Function to dispose the fragments received for a message
1723  * @param session session to free the fragments from
1724  */
1725
1726 static void
1727 free_rec_frag_queue(struct Session * session)
1728 {
1729   struct RecQueue * rec_queue = session->frag_head;
1730   struct RecQueue * rec_queue2;
1731   while (rec_queue != NULL)
1732     {
1733       rec_queue2 = rec_queue;
1734       rec_queue = rec_queue->next;
1735       GNUNET_free(rec_queue2);
1736     }
1737   session->frag_head = NULL;
1738   session->frag_tail = NULL;
1739   session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1740 }
1741
1742 /**
1743  * Function to check if all fragments of a message have been received
1744  * @param plugin the plugin handle
1745  * @param session_light information of the message sender
1746  * @param session session the message belongs to
1747  */
1748
1749 static void
1750 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1751   struct RecQueue * rec_queue = session->frag_head;
1752   int packetsize = session->rec_size;
1753   int sum = 0;
1754   int aktnum = 0;
1755   char * msg;
1756   //some fragment should be received
1757   GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1758   //check if first fragment is present
1759   if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1760     return;
1761   }
1762   while (rec_queue != NULL){
1763     sum += rec_queue->size;
1764     //check if all fragment numbers are present
1765     if (rec_queue->num != aktnum){
1766       return;
1767     }
1768     aktnum ++;
1769     rec_queue = rec_queue->next;
1770   }
1771   //sum should always be smaller or equal of
1772   GNUNET_assert(sum <= packetsize);
1773   if(sum == packetsize){
1774
1775 #if DEBUG_wlan
1776       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1777           "check_rec_finished_msg: A message with fragments is complete\n");
1778 #endif
1779
1780     //copy fragments together
1781     msg = GNUNET_malloc(packetsize);
1782     rec_queue = session->frag_head;
1783     aktnum = 0;
1784     while (rec_queue != NULL){
1785       memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1786       aktnum += rec_queue->size;
1787       rec_queue = rec_queue->next;
1788     }
1789     free_rec_frag_queue(session);
1790     //call wlan_process_helper to process the message
1791     wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1792
1793     GNUNET_free(msg);
1794   }
1795 }
1796
1797 /**
1798  * Function used for to process the data received from the wlan interface
1799  *
1800  * @param cls the plugin handle
1801  * @param client client which send the data (not used)
1802  * @param hdr hdr of the GNUNET_MessageHeader
1803  */
1804 static void
1805 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr)
1806 {
1807   struct Plugin *plugin = cls;
1808   struct Session * session = NULL;
1809   struct Session_light * session_light = NULL;
1810
1811   struct WlanHeader * wlanheader = NULL;
1812   struct FragmentationHeader * fh = NULL;
1813   struct FragmentMessage * fm = NULL;
1814
1815   const char * tempmsg = NULL;
1816
1817   struct AckQueue * ack = NULL;
1818   struct AckQueue * ack2 = NULL;
1819
1820   struct RecQueue * rec_queue = NULL;
1821   const struct GNUNET_MessageHeader * temp_hdr = NULL;
1822
1823   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1824     {
1825
1826 #if DEBUG_wlan
1827       GNUNET_log(
1828           GNUNET_ERROR_TYPE_DEBUG,
1829           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %i\n",
1830           ntohs(hdr->size));
1831 #endif
1832
1833       //TODO better DOS protection, error handling
1834       GNUNET_assert(client != NULL);
1835       session_light = (struct Session_light *) client;
1836       if (session_light->session == NULL)
1837         {
1838           session_light->session = get_Session(plugin, session_light->addr);
1839         }
1840       GNUNET_assert(GNUNET_HELLO_get_id(
1841               (const struct GNUNET_HELLO_Message *) &hdr[1],
1842               &(session_light->session->target) ) != GNUNET_SYSERR);
1843
1844     }
1845
1846
1847     else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1848     {
1849
1850 #if DEBUG_wlan
1851       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1852           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %i\n",
1853           ntohs(hdr->size));
1854 #endif
1855
1856       GNUNET_assert(client != NULL);
1857       session_light = (struct Session_light *) client;
1858       if (session_light->session == NULL)
1859         {
1860           session_light->session = search_session(plugin, session_light->addr);
1861         }
1862       session = session_light->session;
1863       wlanheader = (struct WlanHeader *) &hdr;
1864       tempmsg = (char*) &wlanheader[1];
1865       temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
1866
1867       if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc)
1868         {
1869           //wrong crc, dispose message
1870           GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN message crc was wrong\n");
1871           return;
1872         }
1873
1874       //if not in session list
1875       if (session == NULL)
1876         {
1877
1878           //try if it is a hello message
1879           if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
1880             {
1881               session = create_session(plugin, session_light->addr);
1882               session_light->session = session;
1883               GNUNET_assert(GNUNET_HELLO_get_id(
1884                       (const struct GNUNET_HELLO_Message *) temp_hdr,
1885                       &session->target ) != GNUNET_SYSERR);
1886
1887             }
1888           else
1889             {
1890               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1891                   "WLAN client not in session list and not a hello message\n");
1892               return;
1893             }
1894         }
1895       //"receive" the message
1896       struct GNUNET_TRANSPORT_ATS_Information distance[2];
1897       distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1898       distance[0].value = htonl(1);
1899       distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1900       distance[1].value = htonl(0);
1901       plugin->env->receive(plugin, &session->target, temp_hdr,
1902           (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1903           session, session->addr, sizeof(session->addr));
1904     }
1905
1906   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1907     {
1908
1909 #if DEBUG_wlan
1910       GNUNET_log(
1911           GNUNET_ERROR_TYPE_DEBUG,
1912           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT size: %i\n",
1913           ntohs(hdr->size));
1914 #endif
1915
1916       GNUNET_assert(client != NULL);
1917       session_light = (struct Session_light *) client;
1918       if (session_light->session == NULL)
1919         {
1920           session_light->session = search_session(plugin, session_light->addr);
1921         }
1922       session = session_light->session;
1923
1924       fh = (struct FragmentationHeader *) hdr;
1925       tempmsg = (char*) &fh[1];
1926
1927       //if not in session list
1928       if (session != NULL)
1929         {
1930           if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1931             {
1932               //wrong crc, dispose message
1933               GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1934                   "WLAN fragment crc was wrong\n");
1935               return;
1936             }
1937           else
1938             {
1939               //todo fragments do not timeout
1940               //check if message_id is rigth or it is a new msg
1941               if ((session->message_id_in == ntohs(fh->message_id))
1942                   || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1943                 {
1944                   session->message_id_in = ntohs(fh->message_id);
1945                   if (is_double_msg(session, fh) != GNUNET_YES)
1946                     {
1947                       rec_queue
1948                           = GNUNET_malloc(sizeof (struct RecQueue) +
1949                               ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1950                       rec_queue->size = ntohs(fh->header.size
1951                           - sizeof(struct FragmentationHeader));
1952                       rec_queue->num = ntohs(fh->fragment_off_or_num);
1953                       rec_queue->msg = (char*) &rec_queue[1];
1954                       //copy msg to buffer
1955                       memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1956                       insert_fragment_in_queue(session, rec_queue);
1957                       check_rec_finished_msg(plugin, session_light, session);
1958                     }
1959                   else
1960                     {
1961                       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1962                           "WLAN fragment is a clone\n");
1963                       return;
1964                     }
1965                 }
1966               else
1967                 {
1968                   GNUNET_log(
1969                       GNUNET_ERROR_TYPE_INFO,
1970                       "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
1971                   return;
1972                 }
1973             }
1974         }
1975       else
1976         {
1977           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1978               "WLAN client not in session list and it is a fragment message\n");
1979           return;
1980         }
1981
1982     }
1983
1984   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1985     {
1986
1987 #if DEBUG_wlan
1988       GNUNET_log(
1989           GNUNET_ERROR_TYPE_DEBUG,
1990           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %i\n",
1991           ntohs(hdr->size));
1992 #endif
1993
1994       GNUNET_assert(client != NULL);
1995       session_light = (struct Session_light *) client;
1996       if (session_light->session == NULL)
1997         {
1998           session_light->session = search_session(plugin, session_light->addr);
1999           GNUNET_assert(session_light->session != NULL);
2000         }
2001       session = session_light->session;
2002       fh = (struct FragmentationHeader *) &hdr[1];
2003       if (fh->message_id == session->message_id_out)
2004         {
2005           fm = get_fragment_message_from_session(session);
2006           if (fm != NULL)
2007             {
2008
2009               ack2 = fm->head;
2010               while (ack2 != NULL)
2011                 {
2012                   // check for double
2013                   if (ack2->fragment_num != fh->fragment_off_or_num)
2014                     {
2015                       // check if next ack has bigger number
2016                       if (ack2->fragment_num > fh->fragment_off_or_num)
2017                         {
2018                           ack = GNUNET_malloc(sizeof(struct AckQueue));
2019                           ack->fragment_num = fh->fragment_off_or_num;
2020                           GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
2021                           //check if finished
2022                           check_finished_fragment(plugin, fm);
2023                           return;
2024                         }
2025                     }
2026                   else
2027                     {
2028                       //double ack
2029                       return;
2030                     }
2031                   ack2 = ack2->next;
2032                 }
2033               //GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
2034               //should never happen but...
2035               //check_finished_fragment(plugin, fm);
2036             }
2037           else
2038             {
2039               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2040                   "WLAN fragment not in fragment list but id is right\n");
2041               return;
2042             }
2043
2044         }
2045
2046     }
2047   else
2048     {
2049       // TODO Wrong data?
2050       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2051           "WLAN packet inside the WLAN helper packet has not the right type\n");
2052       return;
2053     }
2054
2055 }
2056
2057 /**
2058  * Function used for to process the data from the suid process
2059  *
2060  * @param cls the plugin handle
2061  * @param client which send the data (not used)
2062  * @param hdr of the GNUNET_MessageHeader
2063  */
2064
2065 static void
2066 wlan_process_helper (void *cls,
2067                       void *client,
2068                       const struct GNUNET_MessageHeader *hdr)
2069 {
2070   struct Plugin *plugin = cls;
2071   struct IeeeHeader * wlanIeeeHeader = NULL;
2072   struct Session_light * session_light = NULL;
2073   const struct GNUNET_MessageHeader * temp_hdr = NULL;
2074
2075   int pos = 0;
2076
2077
2078   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
2079     {
2080 #if DEBUG_wlan
2081       GNUNET_log(
2082           GNUNET_ERROR_TYPE_DEBUG,
2083           "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %i\n",
2084           ntohs(hdr->size));
2085 #endif
2086
2087       //call wlan_process_helper with the message inside, later with wlan: analyze signal
2088       GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
2089       wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
2090
2091       session_light = GNUNET_malloc(sizeof(struct Session_light));
2092       memcpy(session_light->addr, &(wlanIeeeHeader->mac3), sizeof(struct MacAddress));
2093       session_light->session = search_session(plugin, session_light->addr);
2094
2095       //process only if it is an broadcast or for this computer both with the gnunet bssid
2096       //check for bssid
2097       if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress)))
2098         {
2099           //check for broadcast or mac
2100           if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac, sizeof(struct MacAddress))
2101               || memcmp(&(wlanIeeeHeader->mac1), &(plugin->mac_address),
2102                   sizeof(struct MacAddress)))
2103             {
2104               // process the inner data
2105             pos = 0;
2106             temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2107               while (pos < hdr->size)
2108                 {
2109                   wlan_data_helper(plugin, &session_light, temp_hdr);
2110                   pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
2111                 }
2112             }
2113         }
2114
2115       //clean up
2116       GNUNET_free(session_light);
2117
2118     }
2119
2120
2121
2122   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
2123     {
2124
2125
2126 #if DEBUG_wlan
2127       GNUNET_log(
2128           GNUNET_ERROR_TYPE_DEBUG,
2129           "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %i\n",
2130           ntohs(hdr->size));
2131 #endif
2132
2133       //TODO more control
2134       //TODO use struct wlan_helper_control
2135       if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
2136         {
2137           //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
2138           memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
2139           GNUNET_log(
2140               GNUNET_ERROR_TYPE_DEBUG,
2141               "Notifying transport of address %s\n",
2142               wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(hdr->size) - sizeof(struct GNUNET_MessageHeader)));
2143           plugin->env->notify_address(plugin->env->cls, "wlan",
2144               &plugin->mac_address, sizeof(struct MacAddress),
2145               GNUNET_TIME_UNIT_FOREVER_REL);
2146         }
2147       else
2148         {
2149           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
2150               plugin->mac_address);
2151         }
2152
2153     }
2154
2155
2156   else
2157     {
2158       // TODO Wrong data?
2159       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN helper packet has not the right type\n");
2160       return;
2161     }
2162 }
2163
2164 /**
2165  * We have been notified that wlan-helper has written something to stdout.
2166  * Handle the output, then reschedule this function to be called again once
2167  * more is available.
2168  *
2169  * @param cls the plugin handle
2170  * @param tc the scheduling context
2171  */
2172
2173 static void
2174 wlan_plugin_helper_read (void *cls,
2175                          const struct GNUNET_SCHEDULER_TaskContext *tc)
2176 {
2177   struct Plugin *plugin = cls;
2178   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2179
2180 #if DEBUG_wlan
2181       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2182                       "Start reading from STDIN\n");
2183 #endif
2184
2185   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2186     return;
2187
2188   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2189   ssize_t bytes;
2190
2191   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
2192                                  mybuf, sizeof(mybuf));
2193   if (bytes <= 0)
2194     {
2195 #if DEBUG_wlan
2196       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2197                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
2198 #endif
2199       return;
2200     }
2201   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
2202                             mybuf, bytes, GNUNET_NO, GNUNET_NO);
2203
2204   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2205   plugin->server_read_task =
2206   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
2207                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
2208 }
2209
2210
2211 /**
2212  * Start the gnunet-wlan-helper process.
2213  *
2214  * @param plugin the transport plugin
2215  * @param testmode should we use the dummy driver for testing?
2216  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2217  */
2218 static int
2219 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2220 {
2221   const char * filename = "gnunet-transport-wlan-helper";
2222   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2223   if (plugin->server_stdout == NULL)
2224     return GNUNET_SYSERR;
2225
2226   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2227   if (plugin->server_stdin == NULL)
2228     return GNUNET_SYSERR;
2229
2230 #if DEBUG_wlan
2231   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2232       "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename, plugin->interface, testmode);
2233 #endif
2234   /* Start the server process */
2235
2236
2237   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2238                   plugin->server_stdout, filename,filename, plugin->interface, ((testmode==1)?"1":(testmode==2)?"2":"0"), NULL);
2239   if (plugin->server_proc == NULL)
2240     {
2241 #if DEBUG_wlan
2242       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2243           "Failed to start gnunet-wlan-helper process\n");
2244 #endif
2245       return GNUNET_SYSERR;
2246     }
2247
2248   /* Close the write end of the read pipe */
2249   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2250
2251   /* Close the read end of the write pipe */
2252   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2253
2254   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2255       GNUNET_DISK_PIPE_END_READ);
2256   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2257       GNUNET_DISK_PIPE_END_WRITE);
2258
2259   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2260
2261 #if DEBUG_wlan
2262   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2263       "Adding server_read_task for the wlan-helper\n");
2264 #endif
2265
2266   sleep(2);
2267
2268   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2269       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2270       &wlan_plugin_helper_read, plugin);
2271
2272   return GNUNET_YES;
2273 }
2274
2275
2276 /**
2277  * Exit point from the plugin.
2278  */
2279 //TODO doxigen
2280 //FIXME cleanup
2281 void *
2282 libgnunet_plugin_transport_wlan_done (void *cls)
2283 {
2284   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2285   struct Plugin *plugin = api->cls;
2286
2287 #if DEBUG_wlan
2288   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2289       "libgnunet_plugin_transport_wlan_done started\n");
2290 #endif
2291
2292   GNUNET_assert(cls !=NULL);
2293
2294   if (plugin->consoltoken != NULL)
2295   GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2296
2297   GNUNET_free_non_null(plugin->interface);
2298   GNUNET_free (plugin);
2299   GNUNET_free (api);
2300   return NULL;
2301 }
2302
2303 /**
2304  * Entry point for the plugin.
2305  *
2306  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2307  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2308  */
2309 void *
2310 libgnunet_plugin_transport_wlan_init (void *cls)
2311 {
2312   //struct GNUNET_SERVICE_Context *service;
2313   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2314   struct GNUNET_TRANSPORT_PluginFunctions *api;
2315   struct Plugin *plugin;
2316   static unsigned long long testmode =0;
2317
2318   GNUNET_assert(cls !=NULL);
2319
2320   plugin = GNUNET_malloc (sizeof (struct Plugin));
2321   plugin->env = env;
2322   plugin->pendingsessions = 0;
2323   plugin->session_count = 0;
2324   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2325   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2326   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2327
2328
2329   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2330     {
2331       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg, "transport-wlan",
2332           "TESTMODE", &testmode))
2333         return NULL;
2334     }
2335
2336   if (GNUNET_CONFIGURATION_have_value(env->cfg,
2337                   "transport-wlan", "INTERFACE"))
2338         {
2339            if (GNUNET_CONFIGURATION_get_value_string (env->cfg,
2340                           "transport-wlan","INTERFACE", &(plugin->interface)) != GNUNET_YES){
2341                    libgnunet_plugin_transport_wlan_done(plugin);
2342                    return NULL;
2343            }
2344         }
2345
2346   wlan_transport_start_wlan_helper(plugin, testmode);
2347   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2348
2349   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2350   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2351
2352   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2353   api->cls = plugin;
2354   api->send = &wlan_plugin_send;
2355   api->disconnect = &wlan_plugin_disconnect;
2356   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2357   api->check_address = &wlan_plugin_address_suggested;
2358   api->address_to_string = &wlan_plugin_address_to_string;
2359
2360
2361   start_next_message_id();
2362
2363 #if DEBUG_wlan
2364   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2365       "wlan init finished\n");
2366 #endif
2367
2368   return api;
2369 }
2370
2371 /* end of plugin_transport_wlan.c */