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