Memory and assertion errors fixed
[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       plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
823     }
824   fm = plugin->pending_Fragment_Messages_head;
825
826   GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
827
828   //check if there are some fragments in the queue
829   if (fm != NULL)
830     {
831       next_send
832           = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
833     }
834   plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
835       &delay_fragment_task, plugin);
836 }
837
838
839
840 //TODO doxigen
841 /**
842  * Function to get the next queued Session, removes the session from the queue
843  */
844
845 static struct Session *
846 get_next_queue_Session (struct Plugin * plugin){
847         struct Session * session;
848         struct Sessionqueue * sessionqueue;
849         struct Sessionqueue * sessionqueue_alt;
850         struct PendingMessage * pm;
851         sessionqueue = plugin->pending_Sessions;
852         while (sessionqueue != NULL){
853                 session = sessionqueue->content;
854                 pm = session->pending_message;
855
856                 //check for message timeout
857                 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
858                         //check if session has no message in the fragment queue
859                         if (! session->has_fragment){
860                                 plugin->pendingsessions --;
861                                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
862                                                 plugin->pending_Sessions_tail, sessionqueue);
863                                 GNUNET_free(sessionqueue);
864
865                                 return session;
866                         } else {
867                                 sessionqueue = sessionqueue->next;
868                         }
869                 } else {
870
871                         session->pending_message = NULL;
872                         //call the cont func that it did not work
873                         if (pm->transmit_cont != NULL)
874                           pm->transmit_cont (pm->transmit_cont_cls,
875                                                 &(session->target), GNUNET_SYSERR);
876                         GNUNET_free(pm->msg);
877                         GNUNET_free(pm);
878
879                         sessionqueue_alt = sessionqueue;
880                         sessionqueue = sessionqueue->next;
881                         plugin->pendingsessions --;
882                         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
883                                         plugin->pending_Sessions_tail, sessionqueue_alt);
884
885                         GNUNET_free(sessionqueue_alt);
886
887                 }
888
889
890         }
891         return NULL;
892 }
893
894
895 /**
896  * Function to sort the message into the message fragment queue
897  * @param plugin the plugin struct
898  * @param fm message to sort into the queue
899  */
900 static void
901 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
902         struct FragmentMessage * fm2;
903         //sort into the list at the right position
904
905         fm2 = plugin->pending_Fragment_Messages_head;
906
907         while (fm2 != NULL){
908                 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
909                         break;
910                 } else {
911                         fm2 = fm2->next;
912                 }
913         }
914
915         GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
916                         plugin->pending_Fragment_Messages_tail,fm2,fm);
917 }
918
919 /**
920  * frees the space of a message in the fragment queue (send queue)
921  * @param plugin the plugin struct
922  * @param fm message to free
923  */
924 static void
925 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
926 {
927   if (fm != NULL)
928     {
929       free_acks(fm);
930       GNUNET_free_non_null(fm->msg);
931       GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
932           plugin->pending_Fragment_Messages_tail, fm);
933       GNUNET_free(fm);
934       plugin->pending_fragment_messages --;
935       check_fragment_queue(plugin);
936     }
937 }
938
939 /**
940  * Function to check if there is some space in the fragment queue
941  * inserts a message if space is available
942  * @param plugin the plugin struct
943  */
944
945 static void
946 check_fragment_queue (struct Plugin * plugin){
947         struct Session * session;
948         struct FragmentMessage * fm;
949
950         struct PendingMessage * pm;
951
952         if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
953                 session = get_next_queue_Session(plugin);
954                 if (session != NULL){
955                         pm = session->pending_message;
956                         session->pending_message = NULL;
957                         session->has_fragment = 1;
958                         GNUNET_assert(pm != NULL);
959
960                         fm = GNUNET_malloc(sizeof(struct FragmentMessage));
961                         fm->message_size = pm->message_size;
962                         fm->msg = pm->msg;
963                         fm->session = session;
964                         fm->timeout.abs_value = pm->timeout.abs_value;
965                         fm->message_pos = 0;
966                         fm->next_ack = GNUNET_TIME_absolute_get();
967
968                         if (pm->transmit_cont != NULL)
969                                   pm->transmit_cont (pm->transmit_cont_cls,
970                                                         &(session->target), GNUNET_OK);
971                         GNUNET_free(pm);
972
973                         sort_fragment_into_queue(plugin,fm);
974                         plugin->pending_fragment_messages ++;
975
976                         //generate new message id
977                         session->message_id_out = get_next_message_id();
978
979                         //check if timeout changed
980                         check_next_fragment_timeout(plugin);
981                 }
982         }
983 }
984
985 /**
986  * Funktion to check if all fragments where send and the acks received
987  * frees the space if finished
988  * @param plugin the plugin struct
989  * @param fm the message to check
990  */
991 static void
992 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
993   struct AckQueue * ack;
994   int counter = 0;
995
996   if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
997       * fm->tail->fragment_num)
998     {
999       ack = fm->head;
1000       counter = 0;
1001       //check if all acks are present
1002       while (ack != NULL)
1003         {
1004           if (counter == ack->fragment_num)
1005             {
1006               counter ++;
1007               ack = ack->next;
1008             } else {
1009               //ack is missing
1010               return;
1011             }
1012         }
1013       fm->session->has_fragment = 0;
1014       free_fragment_message(plugin, fm);
1015
1016
1017     }
1018 }
1019
1020 /**
1021  * Function called when wlan helper is ready to get some data
1022  *
1023  * @param cls closure
1024  * @param tc GNUNET_SCHEDULER_TaskContext
1025  */
1026
1027 static void
1028 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1029 {
1030
1031   struct Plugin * plugin = cls;
1032   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1033
1034   ssize_t bytes;
1035
1036   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1037     return;
1038
1039   struct Session * session = NULL;
1040   struct FragmentMessage * fm = NULL;
1041   struct IeeeHeader * ieeewlanheader = NULL;
1042   struct RadiotapHeader * radioHeader = NULL;
1043   struct GNUNET_MessageHeader * msgheader = NULL;
1044
1045   struct FragmentationHeader fragheader;
1046   struct FragmentationHeader * fragheaderptr = NULL;
1047   struct Finish_send * finish = NULL;
1048   uint16_t size = 0;
1049   const char * copystart = NULL;
1050   uint16_t copysize = 0;
1051   uint copyoffset = 0;
1052   struct AckQueue * akt = NULL;
1053
1054
1055   struct GNUNET_MessageHeader * msgheader2 = NULL;
1056
1057   //test if a "hello-beacon" has to be send
1058   if (0==1)
1059   //if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1060     {
1061       //check if the message is not to big
1062       GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1063               *(plugin->env->our_hello)) <= WLAN_MTU);
1064       size = sizeof(struct GNUNET_MessageHeader)
1065           + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1066           + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1067           *(plugin->env->our_hello));
1068
1069       msgheader = GNUNET_malloc(size);
1070       msgheader->size = htons(size);
1071       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1072
1073       radioHeader = (struct RadiotapHeader *) &msgheader[1];
1074       getRadiotapHeader(radioHeader);
1075
1076       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1077       getWlanHeader(ieeewlanheader);
1078
1079       msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1080       msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1081           + sizeof(struct GNUNET_MessageHeader));
1082       msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1083
1084       memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1085           *(plugin->env->our_hello)));
1086
1087       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1088           size);
1089       if (bytes == GNUNET_SYSERR)
1090         {
1091           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1092               _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1093               errno, strerror(errno));
1094
1095         }
1096       GNUNET_assert(bytes != GNUNET_SYSERR);
1097       GNUNET_assert(bytes == size);
1098
1099       GNUNET_free(msgheader);
1100
1101       set_next_beacon_time(plugin);
1102       check_next_fragment_timeout(plugin);
1103
1104       return;
1105
1106     }
1107
1108
1109
1110   fm = plugin->pending_Fragment_Messages_head;
1111   GNUNET_assert(fm != NULL);
1112   session = fm->session;
1113   GNUNET_assert(session != NULL);
1114
1115   // test if message timed out
1116   if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1117     {
1118       free_acks(fm);
1119       GNUNET_assert(plugin->pending_fragment_messages > 0);
1120       plugin->pending_fragment_messages--;
1121       GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1122           plugin->pending_Fragment_Messages_tail, fm);
1123
1124       GNUNET_free(fm->msg);
1125
1126       GNUNET_free(fm);
1127       check_fragment_queue(plugin);
1128     }
1129   else
1130     {
1131
1132       if (fm->message_size > WLAN_MTU)
1133         {
1134           size += sizeof(struct FragmentationHeader);
1135           // check/set for retransmission
1136           if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0)
1137             {
1138
1139               // be positive and try again later :-D
1140               fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(
1141                   fm));
1142               // find first missing fragment
1143               akt = fm->head;
1144               fm->message_pos = 0;
1145
1146               //test if ack 0 was already received
1147               while (akt != NULL)
1148                 {
1149                   //if fragment is present, take next
1150                   if (akt->fragment_num == fm->message_pos)
1151                     {
1152                       fm->message_pos++;
1153                     }
1154                   //next ack is bigger then the fragment number
1155                   //in case there is something like this: (acks) 1, 2, 5, 6, ...
1156                   //and we send 3 again, the next number should be 4
1157                   else if (akt->fragment_num > fm->message_pos)
1158                     {
1159                       break;
1160                     }
1161
1162                   akt = akt->next;
1163
1164                 }
1165
1166             }
1167
1168           copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1169               * fm->message_pos;
1170           fragheader.fragment_off_or_num = htons(fm->message_pos);
1171           fragheader.message_id = htonl(session->message_id_out);
1172
1173           // start should be smaller then the packet size
1174           GNUNET_assert(copyoffset < fm->message_size);
1175           copystart = fm->msg + copyoffset;
1176
1177           //size of the fragment is either the MTU - overhead
1178           //or the missing part of the message in case this is the last fragment
1179           copysize = GNUNET_MIN(fm->message_size - copyoffset,
1180               WLAN_MTU - sizeof(struct FragmentationHeader));
1181           fragheader.header.size = htons(copysize
1182               + sizeof(struct FragmentationHeader));
1183           fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1184
1185           //get the next missing fragment
1186           akt = fm->head;
1187           fm->message_pos++;
1188
1189           //test if ack was already received
1190           while (akt != NULL)
1191             {
1192               //if fragment is present, take next
1193               if (akt->fragment_num == fm->message_pos)
1194                 {
1195                   fm->message_pos++;
1196                 }
1197               //next ack is bigger then the fragment number
1198               //in case there is something like this: (acks) 1, 2, 5, 6, ...
1199               //and we send 3 again, the next number should be 4
1200               else if (akt->fragment_num > fm->message_pos)
1201                 {
1202                   break;
1203                 }
1204
1205               akt = akt->next;
1206             }
1207         }
1208       else
1209         {
1210           // there is no need to split
1211           copystart = fm->msg;
1212           copysize = fm->message_size;
1213         }
1214
1215       size += copysize;
1216       size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1217           + sizeof(struct GNUNET_MessageHeader);
1218       msgheader = GNUNET_malloc(size);
1219       msgheader->size = htons(size);
1220       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1221
1222       radioHeader = (struct RadiotapHeader*) &msgheader[1];
1223       getRadiotapHeader(radioHeader);
1224
1225       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1226       getWlanHeader(ieeewlanheader);
1227
1228       //could be faster if content is just send and not copyed before
1229       //fragmentheader is needed
1230       if (fm->message_size > WLAN_MTU)
1231         {
1232           fragheader.message_crc = htons(getcrc16(copystart, copysize));
1233           memcpy(&ieeewlanheader[1], &fragheader,
1234               sizeof(struct FragmentationHeader));
1235           fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1236           memcpy(&fragheaderptr[1], copystart, copysize);
1237         }
1238       else
1239         {
1240           memcpy(&ieeewlanheader[1], copystart, copysize);
1241         }
1242
1243       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1244       if (bytes == GNUNET_SYSERR){
1245         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1246             _("Error writing to wlan healper. errno == %d, ERROR: %s\n"), errno, strerror(errno) );
1247
1248       }
1249       GNUNET_assert(bytes != GNUNET_SYSERR);
1250
1251       if (bytes != size)
1252         {
1253           finish = GNUNET_malloc(sizeof( struct Finish_send));
1254           finish->plugin = plugin;
1255           finish->msgheader = (char * ) msgheader + bytes;
1256           finish->size = size - bytes;
1257           finish->msgstart = msgheader;
1258
1259           GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1260
1261           plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1262               GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1263               &finish_sending, finish);
1264
1265         }
1266       else
1267         {
1268           GNUNET_assert(bytes == size);
1269
1270           GNUNET_free(msgheader);
1271           check_next_fragment_timeout(plugin);
1272         }
1273
1274       //check if this was the last fragment of this message, if true then queue at the end of the list
1275       if (copysize + copyoffset >= fm->message_size)
1276         {
1277           GNUNET_assert(copysize + copyoffset == fm->message_size);
1278
1279           GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1280               plugin->pending_Fragment_Messages_tail, fm);
1281
1282           GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1283               plugin->pending_Fragment_Messages_tail, fm);
1284           // if fragments have opimized timeouts
1285           //sort_fragment_into_queue(plugin,fm);
1286
1287         }
1288
1289     }
1290 }
1291
1292
1293 static void
1294 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1295 {
1296   struct Finish_send * finish;
1297   struct Plugin * plugin;
1298   ssize_t bytes;
1299
1300   finish = cls;
1301   plugin = finish->plugin;
1302
1303   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1304
1305   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, finish->msgheader, finish->size);
1306   GNUNET_assert(bytes != GNUNET_SYSERR);
1307
1308   GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1309   if (bytes != finish->size)
1310     {
1311
1312       finish->plugin = plugin;
1313       finish->msgheader = finish->msgheader + bytes;
1314       finish->size = finish->size - bytes;
1315       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1316           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1317           &finish_sending, finish);
1318     }
1319   else
1320     {
1321       GNUNET_free(finish->msgstart);
1322       GNUNET_free(finish);
1323       check_next_fragment_timeout(plugin);
1324     }
1325
1326 }
1327
1328 int
1329 getRadiotapHeader(struct RadiotapHeader * Header){
1330   return GNUNET_YES;
1331 };
1332
1333 int
1334 getWlanHeader(struct IeeeHeader * Header){
1335
1336   return GNUNET_YES;
1337 }
1338
1339
1340 /**
1341  * 32bit CRC
1342  *
1343  * @param msgbuf pointer tor the data
1344  * @param msgbuf_size size of the data
1345  *
1346  * @return 32bit crc value
1347  */
1348
1349 uint32_t
1350 getcrc32 (const char *msgbuf,
1351                   size_t msgbuf_size){
1352         //TODO calc some crc
1353         return 0;
1354 }
1355
1356 /**
1357  * 16bit CRC
1358  *
1359  * @param msgbuf pointer tor the data
1360  * @param msgbuf_size size of the data
1361  *
1362  * @return 16bit crc value
1363  */
1364
1365 uint16_t
1366 getcrc16 (const char *msgbuf,
1367                   size_t msgbuf_size){
1368         //TODO calc some crc
1369         return 0;
1370 }
1371
1372 /**
1373  * Function that can be used by the transport service to transmit
1374  * a message using the plugin.
1375  *
1376  * @param cls closure
1377  * @param target who should receive this message
1378  * @param priority how important is the message
1379  * @param msgbuf the message to transmit
1380  * @param msgbuf_size number of bytes in 'msgbuf'
1381  * @param timeout when should we time out 
1382  * @param session which session must be used (or NULL for "any")
1383  * @param addr the address to use (can be NULL if the plugin
1384  *                is "on its own" (i.e. re-use existing TCP connection))
1385  * @param addrlen length of the address in bytes
1386  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1387  *                otherwise the plugin may use other addresses or
1388  *                existing connections (if available)
1389  * @param cont continuation to call once the message has
1390  *        been transmitted (or if the transport is ready
1391  *        for the next transmission call; or if the
1392  *        peer disconnected...)
1393  * @param cont_cls closure for cont
1394  * @return number of bytes used (on the physical network, with overheads);
1395  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1396  *         and does NOT mean that the message was not transmitted (DV)
1397  */
1398 static ssize_t
1399 wlan_plugin_send (void *cls,
1400                   const struct GNUNET_PeerIdentity * target,
1401                   const char *msgbuf,
1402                   size_t msgbuf_size,
1403                   unsigned int priority,
1404                   struct GNUNET_TIME_Relative timeout,
1405                   struct Session *session,
1406                   const void *addr,
1407                   size_t addrlen,
1408                   int force_address,
1409                   GNUNET_TRANSPORT_TransmitContinuation cont,
1410                   void *cont_cls)
1411 {
1412   struct Plugin * plugin = cls;
1413   struct PendingMessage * newmsg = NULL;
1414   struct WlanHeader * wlanheader = NULL;
1415   //check if msglen > 0
1416   GNUNET_assert(msgbuf_size > 0);
1417
1418   //get session if needed
1419   if (session == NULL)
1420     {
1421       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1422         {
1423           session = get_Session(plugin, addr);
1424         }
1425       else
1426         {
1427           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1428               _("Wlan Address len %d is wrong\n"), addrlen);
1429           return -1;
1430         }
1431     }
1432
1433   //TODO target "problem" not solved
1434   session->target = *target;
1435
1436   //queue message:
1437   //first queue session
1438   queue_Session(plugin, session);
1439
1440   //queue message in session
1441   //test if there is no other message in the "queue"
1442   GNUNET_assert (session->pending_message == NULL);
1443
1444   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1445   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1446   wlanheader = (struct WlanHeader *) newmsg->msg;
1447   //copy msg to buffer, not fragmented / segmented yet, but with message header
1448   wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1449   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1450   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1451   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1452   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1453   newmsg->transmit_cont = cont;
1454   newmsg->transmit_cont_cls = cont_cls;
1455   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1456   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1457
1458   session->pending_message = newmsg;
1459
1460   check_fragment_queue(plugin);
1461   //FIXME not the correct size
1462   return msgbuf_size;
1463
1464 }
1465
1466 //TODO doxigen
1467 static struct FragmentMessage *
1468 get_fragment_message_from_session(struct Session * session)
1469 {
1470   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1471   while (fm != NULL)
1472     {
1473       if (fm->session == session)
1474         {
1475           return fm;
1476         }
1477       fm = fm->next;
1478     }
1479   return NULL;
1480 }
1481
1482 /**
1483  * Function that can be used to force the plugin to disconnect
1484  * from the given peer and cancel all previous transmissions
1485  * (and their continuation).
1486  *
1487  * @param cls closure
1488  * @param target peer from which to disconnect
1489  */
1490 static void
1491 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1492 {
1493   struct Plugin *plugin = cls;
1494   struct Sessionqueue * queue = plugin->sessions;
1495   struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1496   struct PendingMessage * pm = NULL;
1497   struct FragmentMessage * fm;
1498
1499   // just look at all the session for the needed one
1500   while (queue != NULL)
1501     {
1502       // content is never NULL
1503       GNUNET_assert (queue->content != NULL);
1504       if (memcmp(target, &(queue->content->target),
1505           sizeof(struct GNUNET_PeerIdentity)) == 0)
1506         {
1507           //session found
1508           //is this session pending for send
1509           while (pendingsession != NULL)
1510             {
1511               if (pendingsession->content == queue->content)
1512                 {
1513                   plugin->pendingsessions --;
1514                   GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1515                       plugin->pending_Sessions_tail, pendingsession);
1516                   GNUNET_free(pendingsession);
1517                   break;
1518                 }
1519               pendingsession = pendingsession->next;
1520             }
1521
1522           //is something of this session in the fragment queue?
1523           fm = get_fragment_message_from_session(queue->content);
1524           free_fragment_message(plugin,fm);
1525
1526           //dispose all received fragments
1527           free_rec_frag_queue(queue->content);
1528
1529           // remove PendingMessage
1530           pm = queue->content->pending_message;
1531           GNUNET_free(pm->msg);
1532           GNUNET_free(pm);
1533
1534           GNUNET_free(queue->content);
1535           GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1536           GNUNET_free(queue);
1537           plugin->session_count --;
1538
1539           return;
1540         }
1541       // try next
1542       queue = queue->next;
1543     }
1544 }
1545
1546
1547 /**
1548  * Convert the transports address to a nice, human-readable
1549  * format.
1550  *
1551  * @param cls closure
1552  * @param type name of the transport that generated the address
1553  * @param addr one of the addresses of the host, NULL for the last address
1554  *        the specific address format depends on the transport
1555  * @param addrlen length of the address
1556  * @param numeric should (IP) addresses be displayed in numeric form?
1557  * @param timeout after how long should we give up?
1558  * @param asc function to call on each string
1559  * @param asc_cls closure for asc
1560  */
1561 static void
1562 wlan_plugin_address_pretty_printer (void *cls,
1563                                     const char *type,
1564                                     const void *addr,
1565                                     size_t addrlen,
1566                                     int numeric,
1567                                     struct GNUNET_TIME_Relative timeout,
1568                                     GNUNET_TRANSPORT_AddressStringCallback
1569                                     asc, void *asc_cls)
1570 {
1571   char ret[92];
1572   const unsigned char * input;
1573   
1574   GNUNET_assert(cls !=NULL);
1575   if (addrlen != 6)
1576     {
1577       /* invalid address (MAC addresses have 6 bytes) */
1578       GNUNET_break (0);
1579       asc (asc_cls, NULL);
1580       return;
1581     }
1582   input = (const unsigned char*) addr;
1583   GNUNET_snprintf (ret, 
1584                    sizeof (ret),
1585                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1586                    PROTOCOL_PREFIX, 
1587                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1588   asc (asc_cls, ret);
1589 }
1590
1591
1592
1593 /**
1594  * Another peer has suggested an address for this
1595  * peer and transport plugin.  Check that this could be a valid
1596  * address.  If so, consider adding it to the list
1597  * of addresses.
1598  *
1599  * @param cls closure
1600  * @param addr pointer to the address
1601  * @param addrlen length of addr
1602  * @return GNUNET_OK if this is a plausible address for this peer
1603  *         and transport
1604  */
1605
1606
1607 static int
1608 wlan_plugin_address_suggested (void *cls,
1609                                    const void *addr,
1610                                    size_t addrlen)
1611 {
1612   //struct Plugin *plugin = cls;
1613
1614   /* check if the address is plausible; if so,
1615      add it to our list! */
1616
1617   GNUNET_assert(cls !=NULL);
1618   //FIXME mitm is not checked
1619   //Mac Adress has 6 bytes
1620   if (addrlen == 6){
1621     /* TODO check for bad addresses like milticast, broadcast, etc */
1622     return GNUNET_OK;
1623   } else {
1624     return GNUNET_SYSERR;
1625   }
1626
1627   return GNUNET_SYSERR;
1628 }
1629
1630
1631 /**
1632  * Function called for a quick conversion of the binary address to
1633  * a numeric address.  Note that the caller must not free the 
1634  * address and that the next call to this function is allowed
1635  * to override the address again.
1636  *
1637  * @param cls closure
1638  * @param addr binary address
1639  * @param addrlen length of the address
1640  * @return string representing the same address 
1641  */
1642 static const char* 
1643 wlan_plugin_address_to_string (void *cls,
1644                                const void *addr,
1645                                size_t addrlen)
1646 {
1647   static char ret[40];
1648   const unsigned char * input;
1649   
1650   GNUNET_assert(cls !=NULL);
1651   if (addrlen != 6)
1652     {
1653       /* invalid address (MAC addresses have 6 bytes) */
1654       GNUNET_break (0);
1655       return NULL;
1656     }
1657   input = (const unsigned char*) addr;
1658   GNUNET_snprintf (ret, 
1659                    sizeof (ret),
1660                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1661                    PROTOCOL_PREFIX, 
1662                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1663   return ret;
1664 }
1665
1666 /**
1667  * Function to test if fragment number already exists in the fragments received
1668  *
1669  * @param session session the fragment belongs to
1670  * @param fh Fragmentheader of the fragment
1671  * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
1672  */
1673
1674 static const int
1675 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1676 {
1677   struct RecQueue * rec_queue = session->frag_head;
1678   while (rec_queue != NULL)
1679     {
1680       if (rec_queue->num == fh->fragment_off_or_num)
1681         {
1682           return GNUNET_YES;
1683         }
1684       rec_queue = rec_queue->next;
1685
1686     }
1687   return GNUNET_NO;
1688 }
1689
1690 /**
1691  * Function to insert a fragment in a queue of a session
1692  * @param session session the fragment belongs to
1693  * @param rec_queue fragment to add
1694  */
1695
1696 static void
1697 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1698 {
1699   struct RecQueue * rec_queue2 = session->frag_head;
1700   struct WlanHeader * wlanheader = NULL;
1701   //first received fragment of message
1702   if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1703     {
1704       session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1705     }
1706   //this is the first fragment of the message (fragment id 0)
1707   if (rec_queue->num == 0)
1708     {
1709       wlanheader = (struct WlanHeader *) rec_queue->msg;
1710       session->rec_size = wlanheader->header.size;
1711     }
1712
1713   //sort into list
1714   while (rec_queue2 != NULL)
1715     {
1716       if (rec_queue2->num > rec_queue->num)
1717         {
1718           //next element number is grater than the current num
1719           GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1720           return;
1721         }
1722       rec_queue = rec_queue->next;
1723     }
1724   //no element has a grater number
1725   GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1726 }
1727
1728 /**
1729  * Function to dispose the fragments received for a message
1730  * @param session session to free the fragments from
1731  */
1732
1733 static void
1734 free_rec_frag_queue(struct Session * session)
1735 {
1736   struct RecQueue * rec_queue = session->frag_head;
1737   struct RecQueue * rec_queue2;
1738   while (rec_queue != NULL)
1739     {
1740       rec_queue2 = rec_queue;
1741       rec_queue = rec_queue->next;
1742       GNUNET_free(rec_queue2);
1743     }
1744   session->frag_head = NULL;
1745   session->frag_tail = NULL;
1746   session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1747 }
1748
1749 /**
1750  * Function to check if all fragments of a message have been received
1751  * @param plugin the plugin handle
1752  * @param session_light information of the message sender
1753  * @param session session the message belongs to
1754  */
1755
1756 static void
1757 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1758   struct RecQueue * rec_queue = session->frag_head;
1759   int packetsize = session->rec_size;
1760   int sum = 0;
1761   int aktnum = 0;
1762   char * msg;
1763   //some fragment should be received
1764   GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1765   //check if first fragment is present
1766   if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1767     return;
1768   }
1769   while (rec_queue != NULL){
1770     sum += rec_queue->size;
1771     //check if all fragment numbers are present
1772     if (rec_queue->num != aktnum){
1773       return;
1774     }
1775     aktnum ++;
1776     rec_queue = rec_queue->next;
1777   }
1778   //sum should always be smaller or equal of
1779   GNUNET_assert(sum <= packetsize);
1780   if(sum == packetsize){
1781
1782 #if DEBUG_wlan
1783       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1784           "check_rec_finished_msg: A message with fragments is complete\n");
1785 #endif
1786
1787     //copy fragments together
1788     msg = GNUNET_malloc(packetsize);
1789     rec_queue = session->frag_head;
1790     aktnum = 0;
1791     while (rec_queue != NULL){
1792       memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1793       aktnum += rec_queue->size;
1794       rec_queue = rec_queue->next;
1795     }
1796     free_rec_frag_queue(session);
1797     //call wlan_process_helper to process the message
1798     wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1799
1800     GNUNET_free(msg);
1801   }
1802 }
1803
1804 /**
1805  * Function used for to process the data received from the wlan interface
1806  *
1807  * @param cls the plugin handle
1808  * @param client client which send the data (not used)
1809  * @param hdr hdr of the GNUNET_MessageHeader
1810  */
1811 static void
1812 wlan_data_helper(void *cls, void * client, const struct GNUNET_MessageHeader * hdr)
1813 {
1814   struct Plugin *plugin = cls;
1815   struct Session * session = NULL;
1816   struct Session_light * session_light = NULL;
1817
1818   struct WlanHeader * wlanheader = NULL;
1819   struct FragmentationHeader * fh = NULL;
1820   struct FragmentMessage * fm = NULL;
1821
1822   const char * tempmsg = NULL;
1823
1824   struct AckQueue * ack = NULL;
1825   struct AckQueue * ack2 = NULL;
1826
1827   struct RecQueue * rec_queue = NULL;
1828   const struct GNUNET_MessageHeader * temp_hdr = NULL;
1829
1830   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1831     {
1832
1833 #if DEBUG_wlan
1834       GNUNET_log(
1835           GNUNET_ERROR_TYPE_DEBUG,
1836           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %i\n",
1837           ntohs(hdr->size));
1838 #endif
1839
1840       //TODO better DOS protection, error handling
1841       GNUNET_assert(client != NULL);
1842       session_light = (struct Session_light *) client;
1843       if (session_light->session == NULL)
1844         {
1845           session_light->session = get_Session(plugin, session_light->addr);
1846         }
1847       GNUNET_assert(GNUNET_HELLO_get_id(
1848               (const struct GNUNET_HELLO_Message *) &hdr[1],
1849               &(session_light->session->target) ) != GNUNET_SYSERR);
1850
1851     }
1852
1853
1854     else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1855     {
1856
1857 #if DEBUG_wlan
1858       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1859           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %i\n",
1860           ntohs(hdr->size));
1861 #endif
1862
1863       GNUNET_assert(client != NULL);
1864       session_light = (struct Session_light *) client;
1865       if (session_light->session == NULL)
1866         {
1867           session_light->session = search_session(plugin, session_light->addr);
1868         }
1869       session = session_light->session;
1870       wlanheader = (struct WlanHeader *) hdr;
1871       tempmsg = (char*) &wlanheader[1];
1872       temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
1873
1874       if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc)
1875         {
1876           //wrong crc, dispose message
1877           GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN message crc was wrong\n");
1878           return;
1879         }
1880
1881       //if not in session list
1882       if (session == NULL)
1883         {
1884
1885           //try if it is a hello message
1886           if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
1887             {
1888               session = create_session(plugin, session_light->addr);
1889               session_light->session = session;
1890               GNUNET_assert(GNUNET_HELLO_get_id(
1891                       (const struct GNUNET_HELLO_Message *) temp_hdr,
1892                       &session->target ) != GNUNET_SYSERR);
1893
1894             }
1895           else
1896             {
1897               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1898                   "WLAN client not in session list and not a hello message\n");
1899               return;
1900             }
1901         }
1902
1903       //"receive" the message
1904       struct GNUNET_TRANSPORT_ATS_Information distance[2];
1905       distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1906       distance[0].value = htonl(1);
1907       distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1908       distance[1].value = htonl(0);
1909       plugin->env->receive(plugin->env->cls, &(session->target), temp_hdr,
1910           (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1911           session, session->addr, sizeof(session->addr));
1912
1913     }
1914
1915   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1916     {
1917
1918 #if DEBUG_wlan
1919       GNUNET_log(
1920           GNUNET_ERROR_TYPE_DEBUG,
1921           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT size: %i\n",
1922           ntohs(hdr->size));
1923 #endif
1924
1925       GNUNET_assert(client != NULL);
1926       session_light = (struct Session_light *) client;
1927       if (session_light->session == NULL)
1928         {
1929           session_light->session = search_session(plugin, session_light->addr);
1930         }
1931       session = session_light->session;
1932
1933       fh = (struct FragmentationHeader *) hdr;
1934       tempmsg = (char*) &fh[1];
1935
1936       //if not in session list
1937       if (session != NULL)
1938         {
1939           if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1940             {
1941               //wrong crc, dispose message
1942               GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1943                   "WLAN fragment crc was wrong\n");
1944               return;
1945             }
1946           else
1947             {
1948               //todo fragments do not timeout
1949               //check if message_id is rigth or it is a new msg
1950               if ((session->message_id_in == ntohs(fh->message_id))
1951                   || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1952                 {
1953                   session->message_id_in = ntohs(fh->message_id);
1954                   if (is_double_msg(session, fh) != GNUNET_YES)
1955                     {
1956                       rec_queue
1957                           = GNUNET_malloc(sizeof (struct RecQueue) +
1958                               ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1959                       rec_queue->size = ntohs(fh->header.size
1960                           - sizeof(struct FragmentationHeader));
1961                       rec_queue->num = ntohs(fh->fragment_off_or_num);
1962                       rec_queue->msg = (char*) &rec_queue[1];
1963                       //copy msg to buffer
1964                       memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1965                       insert_fragment_in_queue(session, rec_queue);
1966                       check_rec_finished_msg(plugin, session_light, session);
1967                     }
1968                   else
1969                     {
1970                       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1971                           "WLAN fragment is a clone\n");
1972                       return;
1973                     }
1974                 }
1975               else
1976                 {
1977                   GNUNET_log(
1978                       GNUNET_ERROR_TYPE_INFO,
1979                       "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
1980                   return;
1981                 }
1982             }
1983         }
1984       else
1985         {
1986           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1987               "WLAN client not in session list and it is a fragment message\n");
1988           return;
1989         }
1990
1991     }
1992
1993   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1994     {
1995
1996 #if DEBUG_wlan
1997       GNUNET_log(
1998           GNUNET_ERROR_TYPE_DEBUG,
1999           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %i\n",
2000           ntohs(hdr->size));
2001 #endif
2002
2003       GNUNET_assert(client != NULL);
2004       session_light = (struct Session_light *) client;
2005       if (session_light->session == NULL)
2006         {
2007           session_light->session = search_session(plugin, session_light->addr);
2008           GNUNET_assert(session_light->session != NULL);
2009         }
2010       session = session_light->session;
2011       fh = (struct FragmentationHeader *) &hdr[1];
2012       if (fh->message_id == session->message_id_out)
2013         {
2014           fm = get_fragment_message_from_session(session);
2015           if (fm != NULL)
2016             {
2017
2018               ack2 = fm->head;
2019               while (ack2 != NULL)
2020                 {
2021                   // check for double
2022                   if (ack2->fragment_num != fh->fragment_off_or_num)
2023                     {
2024                       // check if next ack has bigger number
2025                       if (ack2->fragment_num > fh->fragment_off_or_num)
2026                         {
2027                           ack = GNUNET_malloc(sizeof(struct AckQueue));
2028                           ack->fragment_num = fh->fragment_off_or_num;
2029                           GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
2030                           //check if finished
2031                           check_finished_fragment(plugin, fm);
2032                           return;
2033                         }
2034                     }
2035                   else
2036                     {
2037                       //double ack
2038                       return;
2039                     }
2040                   ack2 = ack2->next;
2041                 }
2042               //GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
2043               //should never happen but...
2044               //check_finished_fragment(plugin, fm);
2045             }
2046           else
2047             {
2048               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2049                   "WLAN fragment not in fragment list but id is right\n");
2050               return;
2051             }
2052
2053         }
2054
2055     }
2056   else
2057     {
2058       // TODO Wrong data?
2059       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2060           "WLAN packet inside the WLAN helper packet has not the right type\n");
2061       return;
2062     }
2063
2064 #if 0
2065       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2066           "Helper finished\n");
2067 #endif
2068
2069 }
2070
2071 /**
2072  * Function used for to process the data from the suid process
2073  *
2074  * @param cls the plugin handle
2075  * @param client which send the data (not used)
2076  * @param hdr of the GNUNET_MessageHeader
2077  */
2078
2079 static void
2080 wlan_process_helper (void *cls,
2081                       void *client,
2082                       const struct GNUNET_MessageHeader *hdr)
2083 {
2084   struct Plugin *plugin = cls;
2085   struct IeeeHeader * wlanIeeeHeader = NULL;
2086   struct Session_light * session_light = NULL;
2087   const struct GNUNET_MessageHeader * temp_hdr = NULL;
2088
2089   int pos = 0;
2090
2091
2092   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
2093     {
2094 #if DEBUG_wlan
2095       GNUNET_log(
2096           GNUNET_ERROR_TYPE_DEBUG,
2097           "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %i\n",
2098           ntohs(hdr->size));
2099 #endif
2100
2101       //call wlan_process_helper with the message inside, later with wlan: analyze signal
2102       GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
2103       wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
2104
2105       session_light = GNUNET_malloc(sizeof(struct Session_light));
2106       memcpy(session_light->addr, &(wlanIeeeHeader->mac3), sizeof(struct MacAddress));
2107       session_light->session = search_session(plugin, session_light->addr);
2108
2109       //process only if it is an broadcast or for this computer both with the gnunet bssid
2110       //check for bssid
2111       if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress)))
2112         {
2113           //check for broadcast or mac
2114           if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac, sizeof(struct MacAddress))
2115               || memcmp(&(wlanIeeeHeader->mac1), &(plugin->mac_address),
2116                   sizeof(struct MacAddress)))
2117             {
2118               // process the inner data
2119             pos = 0;
2120             temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2121               while (pos < hdr->size)
2122                 {
2123                   wlan_data_helper(plugin, session_light, temp_hdr);
2124                   pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
2125                 }
2126             }
2127         }
2128
2129       //clean up
2130       GNUNET_free(session_light);
2131
2132     }
2133
2134
2135
2136   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
2137     {
2138
2139
2140 #if DEBUG_wlan
2141       GNUNET_log(
2142           GNUNET_ERROR_TYPE_DEBUG,
2143           "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %i\n",
2144           ntohs(hdr->size));
2145 #endif
2146
2147       //TODO more control
2148       //TODO use struct wlan_helper_control
2149       if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
2150         {
2151           //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
2152           memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
2153           GNUNET_log(
2154               GNUNET_ERROR_TYPE_DEBUG,
2155               "Notifying transport of address %s\n",
2156               wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(hdr->size) - sizeof(struct GNUNET_MessageHeader)));
2157           plugin->env->notify_address(plugin->env->cls, "wlan",
2158               &plugin->mac_address, sizeof(struct MacAddress),
2159               GNUNET_TIME_UNIT_FOREVER_REL);
2160         }
2161       else
2162         {
2163           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
2164               plugin->mac_address);
2165         }
2166
2167     }
2168
2169
2170   else
2171     {
2172       // TODO Wrong data?
2173       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN helper packet has not the right type\n");
2174       return;
2175     }
2176 }
2177
2178 /**
2179  * We have been notified that wlan-helper has written something to stdout.
2180  * Handle the output, then reschedule this function to be called again once
2181  * more is available.
2182  *
2183  * @param cls the plugin handle
2184  * @param tc the scheduling context
2185  */
2186
2187 static void
2188 wlan_plugin_helper_read (void *cls,
2189                          const struct GNUNET_SCHEDULER_TaskContext *tc)
2190 {
2191   struct Plugin *plugin = cls;
2192   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2193
2194 #if DEBUG_wlan
2195       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2196                       "Start reading from STDIN\n");
2197 #endif
2198
2199   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2200     return;
2201
2202   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2203   ssize_t bytes;
2204
2205   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
2206                                  mybuf, sizeof(mybuf));
2207   if (bytes <= 0)
2208     {
2209 #if DEBUG_wlan
2210       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2211                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
2212 #endif
2213       return;
2214     }
2215   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
2216                             mybuf, bytes, GNUNET_NO, GNUNET_NO);
2217
2218   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2219   plugin->server_read_task =
2220   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
2221                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
2222 }
2223
2224
2225 /**
2226  * Start the gnunet-wlan-helper process.
2227  *
2228  * @param plugin the transport plugin
2229  * @param testmode should we use the dummy driver for testing?
2230  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2231  */
2232 static int
2233 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2234 {
2235   const char * filename = "gnunet-transport-wlan-helper";
2236   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2237   if (plugin->server_stdout == NULL)
2238     return GNUNET_SYSERR;
2239
2240   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2241   if (plugin->server_stdin == NULL)
2242     return GNUNET_SYSERR;
2243
2244 #if DEBUG_wlan
2245   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2246       "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename, plugin->interface, testmode);
2247 #endif
2248   /* Start the server process */
2249
2250
2251   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2252                   plugin->server_stdout, filename,filename, plugin->interface, ((testmode==1)?"1":(testmode==2)?"2":"0"), NULL);
2253   if (plugin->server_proc == NULL)
2254     {
2255 #if DEBUG_wlan
2256       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2257           "Failed to start gnunet-wlan-helper process\n");
2258 #endif
2259       return GNUNET_SYSERR;
2260     }
2261
2262   /* Close the write end of the read pipe */
2263   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2264
2265   /* Close the read end of the write pipe */
2266   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2267
2268   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2269       GNUNET_DISK_PIPE_END_READ);
2270   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2271       GNUNET_DISK_PIPE_END_WRITE);
2272
2273   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2274
2275 #if DEBUG_wlan
2276   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2277       "Adding server_read_task for the wlan-helper\n");
2278 #endif
2279
2280   sleep(2);
2281
2282   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2283       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2284       &wlan_plugin_helper_read, plugin);
2285
2286   return GNUNET_YES;
2287 }
2288
2289
2290 /**
2291  * Exit point from the plugin.
2292  */
2293 //TODO doxigen
2294 //FIXME cleanup
2295 void *
2296 libgnunet_plugin_transport_wlan_done (void *cls)
2297 {
2298   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2299   struct Plugin *plugin = api->cls;
2300
2301 #if DEBUG_wlan
2302   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2303       "libgnunet_plugin_transport_wlan_done started\n");
2304 #endif
2305
2306   GNUNET_assert(cls !=NULL);
2307
2308   if (plugin->consoltoken != NULL)
2309   GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2310
2311   GNUNET_free_non_null(plugin->interface);
2312   GNUNET_free (plugin);
2313   GNUNET_free (api);
2314   return NULL;
2315 }
2316
2317 /**
2318  * Entry point for the plugin.
2319  *
2320  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2321  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2322  */
2323 void *
2324 libgnunet_plugin_transport_wlan_init (void *cls)
2325 {
2326   //struct GNUNET_SERVICE_Context *service;
2327   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2328   struct GNUNET_TRANSPORT_PluginFunctions *api;
2329   struct Plugin *plugin;
2330   static unsigned long long testmode =0;
2331
2332   GNUNET_assert(cls !=NULL);
2333
2334   plugin = GNUNET_malloc (sizeof (struct Plugin));
2335   plugin->env = env;
2336   plugin->pendingsessions = 0;
2337   plugin->session_count = 0;
2338   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2339   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2340   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2341
2342
2343   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2344     {
2345       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg, "transport-wlan",
2346           "TESTMODE", &testmode))
2347         return NULL;
2348     }
2349
2350   if (GNUNET_CONFIGURATION_have_value(env->cfg,
2351                   "transport-wlan", "INTERFACE"))
2352         {
2353            if (GNUNET_CONFIGURATION_get_value_string (env->cfg,
2354                           "transport-wlan","INTERFACE", &(plugin->interface)) != GNUNET_YES){
2355                    libgnunet_plugin_transport_wlan_done(plugin);
2356                    return NULL;
2357            }
2358         }
2359
2360   wlan_transport_start_wlan_helper(plugin, testmode);
2361   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2362
2363   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2364   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2365
2366   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2367   api->cls = plugin;
2368   api->send = &wlan_plugin_send;
2369   api->disconnect = &wlan_plugin_disconnect;
2370   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2371   api->check_address = &wlan_plugin_address_suggested;
2372   api->address_to_string = &wlan_plugin_address_to_string;
2373
2374
2375   start_next_message_id();
2376
2377 #if DEBUG_wlan
2378   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2379       "wlan init finished\n");
2380 #endif
2381
2382   return api;
2383 }
2384
2385 /* end of plugin_transport_wlan.c */