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