resolved FIXME to a comment
[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 #include "wlan/ieee80211.h"
38
39 #include <string.h>
40
41 #define PROTOCOL_PREFIX "wlan"
42
43 /**
44  * Max size of packet from helper
45  */
46 #define WLAN_MTU 3000
47
48 /**
49  * Time until retransmission of a fragment in ms
50  */
51 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
52
53 #define FRAGMENT_QUEUE_SIZE 10
54 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
55
56 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
57
58 #define MESSAGES_IN_QUEUE_SIZE 10
59 #define MESSAGES_IN_QUEUE_PER_SESSION 1
60
61 #define HALLO_BEACON_SCALING_FACTOR 900
62
63 #define DEBUG_wlan GNUNET_NO
64
65 #define MESSAGE_LENGHT_UNKNOWN -1
66 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
67
68 /**
69  * After how long do we expire an address that we
70  * learned from another peer if it is not reconfirmed
71  * by anyone?
72  */
73 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
74
75 /**
76  * Initial handshake message for a session.
77  */
78 struct WelcomeMessage
79 {
80   /**
81    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
82    */
83   struct GNUNET_MessageHeader header;
84
85   /**
86    * Identit*mac_y of the node connecting (TCP client)
87    */
88   struct GNUNET_PeerIdentity clientIdentity;
89
90 };
91
92 /**
93  * Encapsulation of all of the state of the plugin.
94  */
95 struct Plugin
96 {
97   /**
98    * Our environment.
99    */
100   struct GNUNET_TRANSPORT_PluginEnvironment *env;
101
102   /**
103    * List of open sessions. head
104    */
105   struct Sessionqueue *sessions;
106
107   /**
108    * List of open sessions. tail
109    */
110   struct Sessionqueue *sessions_tail;
111
112   /**
113    * Number of sessions
114    */
115   unsigned int session_count;
116
117   /**
118    * encapsulation of data from the local wlan helper program
119    */
120   struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
121
122   /**
123    * encapsulation of packets received
124    */
125   struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
126
127   /**
128    * stdout pipe handle for the gnunet-wlan-helper process
129    */
130   struct GNUNET_DISK_PipeHandle *server_stdout;
131
132   /**
133    * stdout file handle for the gnunet-wlan-helper process
134    */
135   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
136
137   /**
138    * stdin pipe handle for the gnunet-wlan-helper process
139    */
140   struct GNUNET_DISK_PipeHandle *server_stdin;
141
142   /**
143    * stdin file handle for the gnunet-wlan-helper process
144    */
145   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
146
147   /**
148    * ID of the gnunet-wlan-server std read task
149    */
150   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
151
152   /**
153    * ID of the gnunet-wlan-server std read task
154    */
155   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
156
157   /**
158    * ID of the delay task for writing
159    */
160   GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
161
162   /**
163    * The process id of the wlan process
164    */
165   struct GNUNET_OS_Process *server_proc;
166
167   /**
168    * The interface of the wlan card given to us by the user.
169    */
170   char *interface;
171
172   /**
173    * The mac_address of the wlan card given to us by the helper.
174    */
175   struct MacAddress mac_address;
176
177   /**
178    * Sessions currently pending for transmission
179    * to this peer, if any.
180    */
181   struct Sessionqueue * pending_Sessions;
182
183   /**
184    * Sessions currently pending for transmission
185    * to this peer (tail), if any.
186    */
187   struct Sessionqueue * pending_Sessions_tail;
188
189   /**
190    * number of pending sessions
191    */
192   unsigned int pendingsessions;
193
194   /**
195    * Messages in the fragmentation queue, head
196    */
197   struct FragmentMessage * pending_Fragment_Messages_head;
198
199   /**
200    * Messages in the fragmentation queue, tail
201    */
202   struct FragmentMessage * pending_Fragment_Messages_tail;
203
204   /**
205    * number of pending fragment message
206    */
207   unsigned int pending_fragment_messages;
208
209   /**
210    * Messages in the in Queue, head
211    */
212   struct Receive_Message_Queue * receive_messages_head;
213
214   /**
215    * Messages in the in Queue, tail
216    */
217   struct Receive_Message_Queue * receive_messages_teil;
218
219   /**
220    * number of messages in the in queue
221    */
222   unsigned int pending_receive_messages;
223
224   /**
225    * time of the next "hello-beacon"
226    */
227   struct GNUNET_TIME_Absolute beacon_time;
228
229   /**
230    * queue to send acks for received fragments (head)
231    */
232   struct AckSendQueue * ack_send_queue_head;
233
234   /**
235    * queue to send acks for received fragments (tail)
236    */
237   struct AckSendQueue * ack_send_queue_tail;
238
239 };
240
241 /**
242  * Struct to store data if file write did not accept the whole packet
243  */
244 struct Finish_send
245 {
246   struct Plugin * plugin;
247   char * msgheader;
248   struct GNUNET_MessageHeader * msgstart;
249   ssize_t size;
250 };
251
252 /**
253  * Queue of sessions, for the general session queue and the pending session queue
254  */
255
256 struct Sessionqueue
257 {
258   struct Sessionqueue * next;
259   struct Sessionqueue * prev;
260   struct Session * content;
261 };
262
263 /**
264  * Queue for the fragments received
265  */
266 struct Receive_Fragment_Queue
267 {
268   struct Receive_Fragment_Queue * next;
269   struct Receive_Fragment_Queue * prev;
270   uint16_t num;
271   const char * msg;
272   uint16_t size;
273   struct Radiotap_rx rxinfo;
274 };
275
276
277 /**
278  * Queue for the fragments received
279  */
280 struct Receive_Message_Queue
281 {
282   struct Receive_Message_Queue * next;
283
284   struct Receive_Message_Queue * prev;
285
286   /**
287    * current number for message incoming, to distinguish between the messages
288    */
289   uint32_t message_id_in;
290
291   /**
292    * size of the message received,
293    * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
294    * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
295    */
296   int rec_size;
297
298   /**
299    * Sorted queue with the fragments received; head
300    */
301
302   struct Receive_Fragment_Queue * frag_head;
303
304   /**
305    * Sorted queue with the fragments received; tail
306    */
307
308   struct Receive_Fragment_Queue * frag_tail;
309
310   /**
311    * Session this fragment belongs to
312    */
313
314   struct Session * session;
315
316   /**
317    * Timeout value for the pending message.
318    */
319   struct GNUNET_TIME_Absolute timeout;
320
321   /**
322    * Bitfield of received fragments
323    */
324
325   uint64_t received_fragments;
326 };
327
328 /**
329  * Information kept for each message that is yet to
330  * be transmitted.
331  */
332 struct PendingMessage
333 {
334
335   /**
336    * The pending message
337    */
338   char *msg;
339
340   /**
341    * Size of the message
342    */
343   size_t message_size;
344
345   /**
346    * Continuation function to call once the message
347    * has been sent.  Can be NULL if there is no
348    * continuation to call.
349    */
350   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
351
352   /**
353    * Cls for transmit_cont
354    */
355   void * transmit_cont_cls;
356
357   /**
358    * Timeout value for the pending message.
359    */
360   struct GNUNET_TIME_Absolute timeout;
361
362 };
363
364 /**
365  * Queue for acks to send for fragments recived
366  */
367 //TODO comments
368 struct AckSendQueue
369 {
370
371   struct AckSendQueue * next;
372   struct AckSendQueue * prev;
373
374   struct Session * session;
375   /**
376    * ID of message, to distinguish between the messages, picked randomly.
377    */
378   uint32_t message_id;
379
380   /**
381    * Bit field for received fragments
382    */
383   uint64_t fragments_field;
384
385 };
386
387 /**
388  * Session infos gathered from a messages
389  */
390
391 struct Session_light
392 {
393   /**
394    * the session this message belongs to
395    */
396   struct Session * session;
397   /**
398    * peer mac address
399    */
400   struct MacAddress addr;
401 };
402
403 /**
404  * Session handle for connections.
405  */
406 struct Session
407 {
408
409   /**
410    * API requirement.
411    */
412   struct SessionHeader header;
413
414   /**
415    * Pointer to the global plugin struct.
416    */
417   struct Plugin *plugin;
418
419   /**
420    * Message currently pending for transmission
421    * to this peer, if any.
422    */
423   struct PendingMessage *pending_message;
424
425   /**
426    * Message currently pending for transmission
427    * to this peer, if any.
428    */
429   struct PendingMessage *pending_message2;
430
431   /**
432    * To whom are we talking to (set to our identity
433    * if we are still waiting for the welcome message)
434    */
435   struct GNUNET_PeerIdentity target;
436
437   /**
438    * peer mac address
439    */
440   struct MacAddress addr;
441
442   /**
443    * Address of the other peer (either based on our 'connect'
444    * call or on our 'accept' call).
445    */
446   void *connect_addr;
447
448   /**
449    * Last activity on this connection.  Used to select preferred
450    * connection.
451    */
452   struct GNUNET_TIME_Absolute last_activity;
453
454   /**
455    * count of messages in the fragment out queue for this session
456    */
457
458   int fragment_messages_out_count;
459
460   /**
461    * count of messages in the fragment in queue for this session
462    */
463
464   int fragment_messages_in_count;
465
466   //TODO DOXIGEN
467   uint8_t rate;
468   uint16_t tx_power;
469   uint8_t antenna;
470
471 };
472
473 /**
474  * Struct for Messages in the fragment queue
475  */
476
477 struct FragmentMessage
478 {
479   /**
480    * Session this message belongs to
481    */
482
483   struct Session *session;
484
485   /**
486    * This is a doubly-linked list.
487    */
488   struct FragmentMessage *next;
489
490   /**
491    * This is a doubly-linked list.
492    */
493   struct FragmentMessage *prev;
494
495   /**
496    * The pending message
497    */
498   char *msg;
499
500   /**
501    * Timeout value for the pending message.
502    */
503   struct GNUNET_TIME_Absolute timeout;
504
505   /**
506    * Timeout value for the pending fragments.
507    * Stores the time when the next msg fragment ack has to be received
508    */
509   struct GNUNET_TIME_Absolute next_ack;
510
511   /**
512    * bitfield with all acks received for this message
513    */
514   uint64_t ack_bitfield;
515
516   /**
517    * Size of the message
518    */
519   size_t message_size;
520
521   /**
522    * pos / next fragment number in the message, for fragmentation/segmentation,
523    * some acks can be missing but there is still time
524    */
525   uint32_t message_pos;
526
527   /**
528    * current number for message outgoing, to distinguish between the messages
529    */
530   uint32_t message_id_out;
531 };
532
533 /**
534  * Header for messages which need fragmentation
535  */
536 struct FragmentationAckHeader
537 {
538
539   struct GNUNET_MessageHeader header;
540
541   /**
542    * ID of message, to distinguish between the messages, picked randomly.
543    */
544   uint32_t message_id GNUNET_PACKED;
545
546   /**
547    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
548    */
549   uint64_t fragment_field GNUNET_PACKED;
550
551 };
552
553 static void
554 do_transmit(void *cls, 
555             const struct GNUNET_SCHEDULER_TaskContext *tc);
556
557
558
559 /**
560  * Sets a bit active in the bitArray. Increment bit-specific
561  * usage counter on disk only if below 4bit max (==15).
562  *
563  * @param bitArray memory area to set the bit in
564  * @param bitIdx which bit to set
565  */
566 static void
567 setBit(char *bitArray, unsigned int bitIdx)
568 {
569   size_t arraySlot;
570   unsigned int targetBit;
571
572   arraySlot = bitIdx / 8;
573   targetBit = (1L << (bitIdx % 8));
574   bitArray[arraySlot] |= targetBit;
575 }
576
577
578 /**
579  * Checks if a bit is active in the bitArray
580  *
581  * @param bitArray memory area to set the bit in
582  * @param bitIdx which bit to test
583  * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
584  */
585 static int
586 testBit(char *bitArray, unsigned int bitIdx)
587 {
588   size_t slot;
589   unsigned int targetBit;
590
591   slot = bitIdx / 8;
592   targetBit = (1L << (bitIdx % 8));
593   if (bitArray[slot] & targetBit)
594     return GNUNET_YES;
595   return GNUNET_NO;
596 }
597
598 /**
599  * get the next message number, at the moment just a random one
600  * @return returns the next valid message-number for sending packets
601  */
602 static uint32_t
603 get_next_message_id()
604 {
605   return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
606 }
607
608
609 /**
610  * search for a session with the addr
611  *
612  * @param plugin pointer to the plugin struct
613  * @param addr pointer to the mac address of the peer
614  * @return returns the session
615  */
616 static struct Session *
617 search_session(struct Plugin *plugin, 
618                const struct MacAddress *addr)
619 {
620   struct Sessionqueue * queue = plugin->sessions;
621
622   while (queue != NULL)
623     {
624       GNUNET_assert (queue->content != NULL);
625       if (memcmp(addr, &queue->content->addr, sizeof (struct MacAddress)) == 0)
626         return queue->content; /* session found */
627       queue = queue->next;
628     }
629   return NULL;
630 }
631
632 /**
633  * create a new session
634  *
635  * @param plugin pointer to the plugin struct
636  * @param addr pointer to the mac address of the peer
637  * @return returns the session
638  */
639
640 static struct Session *
641 create_session(struct Plugin *plugin,
642                const struct MacAddress * addr)
643 {
644   struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
645
646   GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
647
648   queue->content = GNUNET_malloc (sizeof (struct Session));
649   queue->content->plugin = plugin;
650   queue->content->addr = *addr;
651   queue->content->fragment_messages_out_count = 0;
652   queue->content->fragment_messages_in_count = 0;
653
654   plugin->session_count++;
655
656 #if DEBUG_wlan
657   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
658       queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
659 #endif
660
661   return queue->content;
662 }
663
664
665 /**
666  * Get session from address, create if no session exists
667  *
668  * @param plugin pointer to the plugin struct
669  * @param addr pointer to the mac address of the peer
670  * @return returns the session
671  */
672 static struct Session *
673 get_Session (struct Plugin *plugin, 
674              const struct MacAddress *addr)
675 {
676   struct Session * session = search_session(plugin, addr);
677   if (session != NULL)
678     return session;
679   return create_session(plugin, addr);
680 }
681
682
683 /**
684  * Queue the session to send data
685  */
686 //TODO doxigen
687 static void
688 queue_Session(struct Plugin *plugin, struct Session * session)
689 {
690   struct Sessionqueue * queue = plugin->pending_Sessions;
691   struct Sessionqueue * lastitem = NULL;
692
693   while (queue != NULL)
694     {
695       // content is never NULL
696       GNUNET_assert (queue->content != NULL);
697       // is session already in queue?
698       if (session == queue->content)
699         {
700           return;
701         }
702       // try next
703       lastitem = queue;
704       queue = queue->next;
705     }
706
707   // Session is not in the queue
708
709   queue = GNUNET_malloc (sizeof (struct Sessionqueue));
710   queue->content = session;
711
712   //insert at the tail
713   GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
714       plugin->pending_Sessions_tail,
715       plugin->pending_Sessions_tail, queue);
716   plugin->pendingsessions++;
717
718 }
719
720 //TODO doxigen
721 /**
722  * Function to schedule the write task, executed after a delay
723  */
724 static void
725 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
726 {
727   struct Plugin * plugin = cls;
728   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
729
730   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
731     return;
732
733   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
734   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
735     {
736       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
737           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
738           &do_transmit, plugin);
739     }
740 }
741
742 //TODO doxigen
743 /**
744  * Function to calculate the time of the next periodic "hello-beacon"
745  */
746 static void
747 set_next_beacon_time(struct Plugin * const plugin)
748 {
749   //under 10 known peers: once a second
750   if (plugin->session_count < 10)
751     {
752       plugin->beacon_time = GNUNET_TIME_absolute_add(
753           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
754               GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
755     }
756   //under 30 known peers: every 10 seconds
757   else if (plugin->session_count < 30)
758     {
759       plugin->beacon_time = GNUNET_TIME_absolute_add(
760           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
761               GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
762     }
763   //over 30 known peers: once a minute
764   else
765     {
766       plugin->beacon_time = GNUNET_TIME_absolute_add(
767           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
768               GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
769     }
770 }
771
772 //TODO doxigen
773 static struct GNUNET_TIME_Relative
774 get_next_frag_timeout(struct FragmentMessage * fm)
775 {
776   return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
777       fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
778 }
779
780 //TODO doxigen
781 /**
782  * Function to get the timeout value for acks for this session
783  */
784
785 static struct GNUNET_TIME_Relative
786 get_ack_timeout(struct FragmentMessage * fm)
787 {
788   return FRAGMENT_TIMEOUT;
789 }
790
791 /**
792  * Function to set the timer for the next timeout of the fragment queue
793  * @param plugin the handle to the plugin struct
794  */
795 static void
796 check_next_fragment_timeout(struct Plugin * const plugin)
797 {
798   struct FragmentMessage * fm;
799   struct GNUNET_TIME_Relative next_send;
800
801   //cancel old task
802   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
803     {
804       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
805       plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
806     }
807   fm = plugin->pending_Fragment_Messages_head;
808
809   GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
810
811   //check if some acks are in the queue
812   if (plugin->ack_send_queue_head != NULL)
813     {
814       next_send = GNUNET_TIME_UNIT_ZERO;
815     }
816   //check if there are some fragments in the queue
817   else
818     {
819       next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
820       if (fm != NULL)
821         {
822           next_send = GNUNET_TIME_relative_min(next_send,
823               get_next_frag_timeout(fm));
824         }
825     }
826   plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
827       &delay_fragment_task, plugin);
828 }
829
830 //TODO doxigen
831 /**
832  * Function to get the next queued Session, removes the session from the queue
833  */
834
835 static struct Session *
836 get_next_queue_Session(struct Plugin * plugin)
837 {
838   struct Session * session;
839   struct Sessionqueue * sessionqueue;
840   struct Sessionqueue * sessionqueue_alt;
841   struct PendingMessage * pm;
842   sessionqueue = plugin->pending_Sessions;
843   while (sessionqueue != NULL)
844     {
845       session = sessionqueue->content;
846
847       pm = session->pending_message;
848       if (pm == NULL)
849         {
850 #if DEBUG_wlan
851           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
852               "pending message is empty, should not happen. session %p\n",
853               session);
854 #endif
855         }
856       GNUNET_assert(pm != NULL);
857
858       //check for message timeout
859       if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
860         {
861           //check if session has no message in the fragment queue
862           if (session->fragment_messages_out_count
863               < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
864             {
865               plugin->pendingsessions--;
866               GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
867                   plugin->pending_Sessions_tail, sessionqueue);
868               GNUNET_free(sessionqueue);
869
870               return session;
871             }
872           else
873             {
874               sessionqueue = sessionqueue->next;
875             }
876         }
877       else
878         {
879
880           session->pending_message = session->pending_message2;
881           session->pending_message2 = NULL;
882
883           //call the cont func that it did not work
884           if (pm->transmit_cont != NULL)
885             pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
886                 GNUNET_SYSERR);
887           GNUNET_free(pm->msg);
888           GNUNET_free(pm);
889
890           if (session->pending_message == NULL)
891             {
892               sessionqueue_alt = sessionqueue;
893               sessionqueue = sessionqueue->next;
894               plugin->pendingsessions--;
895               GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
896                   plugin->pending_Sessions_tail, sessionqueue_alt);
897
898               GNUNET_free(sessionqueue_alt);
899             }
900
901         }
902
903     }
904   return NULL;
905 }
906
907 /**
908  * Function to sort the message into the message fragment queue
909  * @param plugin the plugin struct
910  * @param fm message to sort into the queue
911  */
912 static void
913 sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
914 {
915   struct FragmentMessage * fm2;
916   //sort into the list at the right position
917
918   fm2 = plugin->pending_Fragment_Messages_head;
919
920   while (fm2 != NULL)
921     {
922       if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
923           == 0)
924         {
925           GNUNET_CONTAINER_DLL_insert_before(plugin->pending_Fragment_Messages_head,
926               plugin->pending_Fragment_Messages_tail,fm2,fm);
927           return;
928         }
929       else
930         {
931           fm2 = fm2->next;
932         }
933     }
934
935   GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
936       plugin->pending_Fragment_Messages_tail,fm);
937 }
938
939 /**
940  * frees the space of a message in the fragment queue (send queue)
941  * @param plugin the plugin struct
942  * @param fm message to free
943  */
944 static void
945 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
946 {
947   if (fm != NULL)
948     {
949       (fm->session->fragment_messages_out_count)--;
950       GNUNET_free_non_null(fm->msg);
951       GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
952           plugin->pending_Fragment_Messages_tail, fm);
953       GNUNET_free(fm);
954       plugin->pending_fragment_messages--;
955
956 #if DEBUG_wlan
957       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
958           "free pending fragment messages, pending messages remaining %u\n",
959           plugin->pending_fragment_messages);
960 #endif
961     }
962 }
963
964 /**
965  * Function to check if there is some space in the fragment queue
966  * inserts a message if space is available
967  * @param plugin the plugin struct
968  */
969
970 static void
971 check_fragment_queue(struct Plugin * plugin)
972 {
973   struct Session * session;
974   struct FragmentMessage * fm;
975   struct GNUNET_PeerIdentity pid;
976
977   struct PendingMessage * pm;
978
979   if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE)
980     {
981       session = get_next_queue_Session(plugin);
982       if (session != NULL)
983         {
984           pm = session->pending_message;
985           session->pending_message = NULL;
986           session->fragment_messages_out_count++;
987           GNUNET_assert(pm != NULL);
988
989           fm = GNUNET_malloc(sizeof(struct FragmentMessage));
990           fm->message_size = pm->message_size;
991           fm->msg = pm->msg;
992           fm->session = session;
993           fm->timeout.abs_value = pm->timeout.abs_value;
994           fm->message_pos = 0;
995           fm->next_ack = GNUNET_TIME_absolute_get();
996           fm->message_id_out = get_next_message_id();
997           fm->ack_bitfield = 0;
998
999           sort_fragment_into_queue(plugin, fm);
1000           plugin->pending_fragment_messages++;
1001
1002           if (pm->transmit_cont != NULL)
1003             {
1004               pid = session->target;
1005               pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1006 #if DEBUG_wlan
1007               GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1008                   "called pm->transmit_cont for %p\n", session);
1009 #endif
1010             }
1011           else
1012             {
1013 #if DEBUG_wlan
1014               GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1015                   "no pm->transmit_cont for %p\n", session);
1016 #endif
1017             }
1018           GNUNET_free(pm);
1019
1020           if (session->pending_message2 != NULL)
1021             {
1022               session->pending_message = session->pending_message2;
1023               session->pending_message2 = NULL;
1024               //requeue session
1025               queue_Session(plugin, session);
1026             }
1027
1028           //check if timeout changed
1029           check_next_fragment_timeout(plugin);
1030         }
1031     }
1032 }
1033
1034 /**
1035  * Funktion to check if all fragments where send and the acks received
1036  * frees the space if finished
1037  * @param plugin the plugin struct
1038  * @param fm the message to check
1039  */
1040 static void
1041 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1042 {
1043   //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1044   unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1045       - sizeof(struct FragmentationHeader)));
1046   uint64_t tmpfield = UINT64_MAX;
1047   tmpfield = tmpfield >> maxack;
1048
1049 #if DEBUG_wlan
1050   if (maxack != 63)
1051     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1052         "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1053         fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1054 #endif
1055
1056   if (fm->ack_bitfield == tmpfield)
1057     {
1058
1059       free_fragment_message(plugin, fm);
1060
1061 #if DEBUG_wlan
1062       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1063           "Finished sending and got all acks for a fragmented message\n");
1064 #endif
1065
1066       check_next_fragment_timeout(plugin);
1067       check_fragment_queue(plugin);
1068
1069     }
1070 }
1071
1072 /**
1073  * Function to set the next fragment number
1074  * @param fm use this FragmentMessage
1075  */
1076
1077 static void
1078 set_next_message_fragment_pos(struct FragmentMessage * fm)
1079 {
1080
1081   //check if retransmit is needed
1082   if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1083     {
1084
1085       // be positive and try again later :-D
1086       fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1087       // find first missing fragment
1088
1089       fm->message_pos = 0;
1090     }
1091
1092   //test if ack 0 (or X) was already received
1093   while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1094     {
1095       fm->message_pos++;
1096     }
1097
1098 }
1099
1100 static int
1101 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1102     struct Radiotap_Send * header)
1103 {
1104
1105   if (session != NULL)
1106     {
1107       header->rate = session->rate;
1108       header->tx_power = session->tx_power;
1109       header->antenna = session->antenna;
1110     }
1111   else
1112     {
1113       header->rate = 255;
1114       header->tx_power = 0;
1115       header->antenna = 0;
1116     }
1117
1118   return GNUNET_YES;
1119 }
1120
1121
1122 /**
1123  * function to generate the wlan hardware header for one packet
1124  * @param Header address to write the header to
1125  * @param to_mac_addr address of the recipient
1126  * @param plugin pointer to the plugin struct
1127  * @return GNUNET_YES if there was no error
1128  */
1129 static int
1130 getWlanHeader(struct ieee80211_frame * Header, 
1131               const struct MacAddress * to_mac_addr,
1132               struct Plugin * plugin)
1133 {
1134   Header->i_fc[0] = 0x80;
1135   Header->i_fc[1] = 0x00;
1136   memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1137   memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1138   memcpy(&Header->i_addr1, to_mac_addr, sizeof(plugin->mac_address));
1139   return GNUNET_YES;
1140 }
1141
1142 /**
1143  * 32bit CRC
1144  *
1145  * @param msgbuf pointer tor the data
1146  * @param msgbuf_size size of the data
1147  *
1148  * @return 32bit crc value
1149  */
1150
1151 uint32_t
1152 getcrc32(const char *msgbuf, size_t msgbuf_size)
1153 {
1154   //TODO calc some crc
1155   return 0;
1156 }
1157
1158 /**
1159  * 16bit CRC
1160  *
1161  * @param msgbuf pointer tor the data
1162  * @param msgbuf_size size of the data
1163  *
1164  * @return 16bit crc value
1165  */
1166
1167 uint16_t
1168 getcrc16(const char *msgbuf, size_t msgbuf_size)
1169 {
1170   //TODO calc some crc
1171   return 0;
1172 }
1173
1174
1175 static void
1176 send_hello_beacon(struct Plugin * plugin)
1177 {
1178
1179 #if DEBUG_wlan
1180   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1181 #endif
1182
1183   uint16_t size;
1184   ssize_t bytes;
1185   struct GNUNET_MessageHeader * msgheader;
1186   struct ieee80211_frame * ieeewlanheader;
1187   struct Radiotap_Send * radioHeader;
1188   struct GNUNET_MessageHeader * msgheader2;
1189
1190   GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1191           *(plugin->env->our_hello)) <= WLAN_MTU);
1192   size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1193       + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1194       + GNUNET_HELLO_size(*(plugin->env->our_hello));
1195
1196   msgheader = GNUNET_malloc(size);
1197   msgheader->size = htons(size);
1198   msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1199
1200   radioHeader = (struct Radiotap_Send*) &msgheader[1];
1201   getRadiotapHeader(plugin, NULL, radioHeader);
1202   ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1203   getWlanHeader(ieeewlanheader, &bc_all_mac, plugin);
1204
1205   msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1206   msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1207       + sizeof(struct GNUNET_MessageHeader));
1208
1209   msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1210   memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1211       *(plugin->env->our_hello)));
1212
1213   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1214
1215   if (bytes == GNUNET_SYSERR)
1216     {
1217       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1218           _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1219           errno, strerror(errno));
1220
1221     }
1222   GNUNET_assert(bytes != GNUNET_SYSERR);
1223   GNUNET_assert(bytes == size);
1224   GNUNET_free(msgheader);
1225
1226   set_next_beacon_time(plugin);
1227   check_next_fragment_timeout(plugin);
1228 }
1229
1230 static void
1231 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1232 {
1233
1234   uint16_t size;
1235   ssize_t bytes;
1236   struct GNUNET_MessageHeader * msgheader;
1237   struct ieee80211_frame * ieeewlanheader;
1238   struct Radiotap_Send * radioHeader;
1239   struct FragmentationAckHeader * msgheader2;
1240
1241   GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1242
1243   size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1244       + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1245
1246 #if DEBUG_wlan
1247   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1248       "Sending ack for message_id %u with fragment field %u, size %u\n",
1249       ack->message_id, ack->fragments_field, size
1250           - sizeof(struct Radiotap_Send));
1251 #endif
1252
1253   msgheader = GNUNET_malloc(size);
1254   msgheader->size = htons(size);
1255   msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1256
1257   radioHeader = (struct Radiotap_Send*) &msgheader[1];
1258   getRadiotapHeader(plugin, ack->session, radioHeader);
1259   ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1260   getWlanHeader(ieeewlanheader, &ack->session->addr, plugin);
1261
1262   msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1263   msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1264   msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1265   msgheader2->message_id = htonl(ack->message_id);
1266   msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1267
1268   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1269   if (bytes == GNUNET_SYSERR)
1270     {
1271       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1272           _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1273           errno, strerror(errno));
1274
1275     }
1276   GNUNET_assert(bytes != GNUNET_SYSERR);
1277   GNUNET_assert(bytes == size);
1278   GNUNET_free(msgheader);
1279   check_next_fragment_timeout(plugin);
1280 }
1281
1282 static void
1283 finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1284 {
1285   struct Finish_send * finish;
1286   struct Plugin * plugin;
1287   ssize_t bytes;
1288
1289   finish = cls;
1290   plugin = finish->plugin;
1291
1292   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1293
1294   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1295       finish->msgheader, finish->size);
1296   GNUNET_assert(bytes != GNUNET_SYSERR);
1297
1298   GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1299   if (bytes != finish->size)
1300     {
1301
1302       finish->msgheader = finish->msgheader + bytes;
1303       finish->size = finish->size - bytes;
1304       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1305           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1306           &finish_sending, finish);
1307     }
1308   else
1309     {
1310       GNUNET_free(finish->msgstart);
1311       GNUNET_free(finish);
1312       check_next_fragment_timeout(plugin);
1313     }
1314
1315 }
1316
1317
1318
1319 /**
1320  * Function called when wlan helper is ready to get some data
1321  *
1322  * @param cls closure
1323  * @param tc GNUNET_SCHEDULER_TaskContext
1324  */
1325 static void
1326 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1327 {
1328
1329   struct Plugin * plugin = cls;
1330   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1331
1332   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1333     return;
1334
1335   struct Session * session = NULL;
1336   struct FragmentMessage * fm = NULL;
1337   struct ieee80211_frame * ieeewlanheader = NULL;
1338   struct Radiotap_Send * radioHeader = NULL;
1339   struct GNUNET_MessageHeader * msgheader = NULL;
1340
1341   struct FragmentationHeader fragheader;
1342   struct FragmentationHeader * fragheaderptr = NULL;
1343   struct Finish_send * finish = NULL;
1344   struct AckSendQueue * ack;
1345   uint16_t size = 0;
1346   ssize_t bytes;
1347   const char * copystart = NULL;
1348   uint16_t copysize = 0;
1349   uint copyoffset = 0;
1350
1351   if (plugin->ack_send_queue_head != NULL)
1352     {
1353       ack = plugin->ack_send_queue_head;
1354       GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1355           plugin->ack_send_queue_tail, ack);
1356       send_ack(plugin, ack);
1357       GNUNET_free(ack);
1358       return;
1359     }
1360
1361   //test if a "hello-beacon" has to be send
1362   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1363     {
1364       send_hello_beacon(plugin);
1365
1366       return;
1367
1368     }
1369
1370   fm = plugin->pending_Fragment_Messages_head;
1371   if (fm != NULL)
1372     {
1373       session = fm->session;
1374       GNUNET_assert(session != NULL);
1375
1376       // test if message timed out
1377       if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1378         {
1379 #if DEBUG_wlan
1380           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1381 #endif
1382
1383           check_fragment_queue(plugin);
1384           free_fragment_message(plugin, fm);
1385
1386         }
1387       else
1388         {
1389
1390           //if (fm->message_size > WLAN_MTU)
1391           // {
1392           size = sizeof(struct FragmentationHeader);
1393
1394           set_next_message_fragment_pos(fm);
1395
1396           copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1397               * fm->message_pos;
1398
1399
1400
1401           fragheader.fragment_off_or_num = htons(fm->message_pos);
1402           fragheader.message_id = htonl(fm->message_id_out);
1403           copystart = fm->msg + copyoffset;
1404           copysize = GNUNET_MIN(fm->message_size - copyoffset,
1405               WLAN_MTU - sizeof(struct FragmentationHeader));
1406
1407 #if DEBUG_wlan
1408           GNUNET_log(
1409               GNUNET_ERROR_TYPE_DEBUG,
1410               "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1411               fm->message_id_out, fm->message_pos, copysize
1412                   + sizeof(struct FragmentationHeader), copyoffset,
1413               GNUNET_TIME_absolute_get_remaining(fm->timeout));
1414 #endif
1415
1416           if (copyoffset >= fm->message_size)
1417             {
1418               GNUNET_log(
1419                   GNUNET_ERROR_TYPE_ERROR,
1420                   "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1421                   copyoffset, fm->message_size, WLAN_MTU
1422                       - sizeof(struct FragmentationHeader), copysize,
1423                   fm->message_pos);
1424             }
1425           GNUNET_assert(copyoffset < fm->message_size);
1426           //FIXME remove later
1427           GNUNET_assert(copystart < fm->msg + fm->message_size);
1428
1429           fragheader.header.size = htons(copysize
1430               + sizeof(struct FragmentationHeader));
1431           fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1432
1433           /* }
1434            else
1435            {
1436            // there is no need to split
1437            copystart = fm->msg;
1438            copysize = fm->message_size;
1439            }*/
1440
1441           size += copysize;
1442           size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1443               + sizeof(struct GNUNET_MessageHeader);
1444           msgheader = GNUNET_malloc(size);
1445           msgheader->size = htons(size);
1446           msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1447
1448           radioHeader = (struct Radiotap_Send*) &msgheader[1];
1449           getRadiotapHeader(plugin, session, radioHeader);
1450
1451           ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1452           getWlanHeader(ieeewlanheader, &fm->session->addr, plugin);
1453
1454           //could be faster if content is just send and not copyed before
1455           //fragmentheader is needed
1456           //if (fm->message_size > WLAN_MTU)
1457           // {
1458           fragheader.message_crc = htons(getcrc16(copystart, copysize));
1459           memcpy(&ieeewlanheader[1], &fragheader,
1460               sizeof(struct FragmentationHeader));
1461           fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1462           memcpy(&fragheaderptr[1], copystart, copysize);
1463           /* }
1464            else
1465            {
1466            memcpy(&ieeewlanheader[1], copystart, copysize);
1467            }*/
1468
1469           bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1470               msgheader, size);
1471           if (bytes == GNUNET_SYSERR)
1472             {
1473               GNUNET_log(
1474                   GNUNET_ERROR_TYPE_ERROR,
1475                   _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1476                   errno, strerror(errno));
1477
1478             }
1479           GNUNET_assert(bytes != GNUNET_SYSERR);
1480
1481           if (bytes != size)
1482             {
1483               finish = GNUNET_malloc(sizeof( struct Finish_send));
1484               finish->plugin = plugin;
1485               finish->msgheader = (char *) msgheader + bytes;
1486               finish->size = size - bytes;
1487               finish->msgstart = msgheader;
1488
1489               GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1490
1491               plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1492                   GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1493                   &finish_sending, finish);
1494
1495             }
1496           else
1497             {
1498               GNUNET_assert(bytes == size);
1499
1500               GNUNET_free(msgheader);
1501               check_next_fragment_timeout(plugin);
1502             }
1503
1504           //check if this was the last fragment of this message, if true then queue at the end of the list
1505           if (copysize + copyoffset >= fm->message_size)
1506             {
1507               GNUNET_assert(copysize + copyoffset == fm->message_size);
1508
1509               GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1510                   plugin->pending_Fragment_Messages_tail, fm);
1511
1512               GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1513                   plugin->pending_Fragment_Messages_tail, fm);
1514               // if fragments have opimized timeouts
1515               //sort_fragment_into_queue(plugin,fm);
1516
1517             }
1518
1519         }
1520       return;
1521     }
1522   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1523       "do_transmit did nothing, should not happen!\n");
1524 }
1525
1526
1527 /**
1528  * Another peer has suggested an address for this
1529  * peer and transport plugin.  Check that this could be a valid
1530  * address.  If so, consider adding it to the list
1531  * of addresses.
1532  *
1533  * @param cls closure
1534  * @param addr pointer to the address
1535  * @param addrlen length of addr
1536  * @return GNUNET_OK if this is a plausible address for this peer
1537  *         and transport
1538  */
1539 static int
1540 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1541 {
1542   //struct Plugin *plugin = cls;
1543
1544   /* check if the address is plausible; if so,
1545    add it to our list! */
1546
1547   GNUNET_assert(cls !=NULL);
1548   //FIXME mitm is not checked
1549   //Mac Address has 6 bytes
1550   if (addrlen == 6)
1551     {
1552       /* TODO check for bad addresses like multicast, broadcast, etc */
1553       return GNUNET_OK;
1554     }
1555
1556   return GNUNET_SYSERR;
1557 }
1558
1559
1560
1561 /**
1562  * Function that can be used by the transport service to transmit
1563  * a message using the plugin.
1564  *
1565  * @param cls closure
1566  * @param target who should receive this message
1567  * @param priority how important is the message
1568  * @param msgbuf the message to transmit
1569  * @param msgbuf_size number of bytes in 'msgbuf'
1570  * @param timeout when should we time out 
1571  * @param session which session must be used (or NULL for "any")
1572  * @param addr the address to use (can be NULL if the plugin
1573  *                is "on its own" (i.e. re-use existing TCP connection))
1574  * @param addrlen length of the address in bytes
1575  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1576  *                otherwise the plugin may use other addresses or
1577  *                existing connections (if available)
1578  * @param cont continuation to call once the message has
1579  *        been transmitted (or if the transport is ready
1580  *        for the next transmission call; or if the
1581  *        peer disconnected...)
1582  * @param cont_cls closure for cont
1583  * @return number of bytes used (on the physical network, with overheads);
1584  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1585  *         and does NOT mean that the message was not transmitted (DV)
1586  */
1587 static ssize_t
1588 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1589     const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1590     struct GNUNET_TIME_Relative timeout, struct Session *session,
1591     const void *addr, size_t addrlen, int force_address,
1592     GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1593 {
1594   struct Plugin * plugin = cls;
1595   struct PendingMessage * newmsg = NULL;
1596   struct WlanHeader * wlanheader = NULL;
1597
1598   //check if msglen > 0
1599   GNUNET_assert(msgbuf_size > 0);
1600
1601   //get session if needed
1602   if (session == NULL)
1603     {
1604       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1605         {
1606           session = get_Session(plugin, addr);
1607         }
1608       else
1609         {
1610           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1611               _("Wlan Address len %d is wrong\n"), addrlen);
1612           return -1;
1613         }
1614     }
1615
1616   //TODO target "problem" not solved
1617   //if (session->target != NULL){
1618   //  GNUNET_assert(session->target == *target);
1619   //} else {
1620   session->target = *target;
1621   //}
1622
1623
1624   //queue message:
1625
1626   //queue message in session
1627   //test if there is no other message in the "queue"
1628   //FIXME: to many send requests
1629   //GNUNET_assert (session->pending_message == NULL);
1630   if (session->pending_message != NULL)
1631     {
1632       newmsg = session->pending_message;
1633       GNUNET_log(
1634           GNUNET_ERROR_TYPE_ERROR,
1635           "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages %u\n",
1636           GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1637           session->fragment_messages_out_count);
1638       if (session->pending_message2 != NULL)
1639         {
1640           GNUNET_log(
1641               GNUNET_ERROR_TYPE_ERROR,
1642               "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1643           return -1;
1644         }
1645     }
1646
1647   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1648   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1649   wlanheader = (struct WlanHeader *) newmsg->msg;
1650   //copy msg to buffer, not fragmented / segmented yet, but with message header
1651   wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1652   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1653   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1654   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1655   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1656   newmsg->transmit_cont = cont;
1657   newmsg->transmit_cont_cls = cont_cls;
1658   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1659
1660   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1661
1662   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1663
1664   if (session->pending_message == NULL)
1665     {
1666       session->pending_message = newmsg;
1667     }
1668   else
1669     {
1670       session->pending_message2 = newmsg;
1671     }
1672
1673 #if DEBUG_wlan
1674   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1675       "New message for %p with size (incl wlan header) %u added\n", session,
1676       newmsg->message_size);
1677 #endif
1678
1679   //queue session
1680   queue_Session(plugin, session);
1681
1682   check_fragment_queue(plugin);
1683   //FIXME not the correct size
1684   return msgbuf_size;
1685
1686 }
1687
1688 /**
1689  * function to get the first message in the fragement queue (out) of a session
1690  * @param session pointer to the session
1691  * @return pointer to the struct FragmentMessage
1692  */
1693 static struct FragmentMessage *
1694 get_fragment_message_from_session(struct Session * session)
1695 {
1696   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1697   while (fm != NULL)
1698     {
1699       if (fm->session == session)
1700         {
1701           return fm;
1702         }
1703       fm = fm->next;
1704     }
1705   return NULL;
1706 }
1707
1708 /**
1709  * function to get the message in the fragement queue (out) of a session with a specific id
1710  * @param session pointer to the session
1711  * @param message_id id of the message
1712  * @return pointer to the struct FragmentMessage
1713  */
1714 static struct FragmentMessage *
1715 get_fragment_message_from_session_and_id(struct Session * session,
1716     uint32_t message_id)
1717 {
1718   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1719   while (fm != NULL)
1720     {
1721       if ((fm->session == session) && (fm->message_id_out == message_id))
1722         {
1723           return fm;
1724         }
1725       fm = fm->next;
1726     }
1727   return NULL;
1728 }
1729
1730
1731 /**
1732  * function to get the receive message of a session
1733  * @param plugin pointer to the plugin struct
1734  * @param session session this fragment belongs to
1735  */
1736 struct Receive_Message_Queue *
1737 get_receive_message_from_session(struct Plugin * plugin,
1738     struct Session * session)
1739 {
1740   struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1741   while (rec_message != NULL)
1742     {
1743       if (rec_message->session == session)
1744         {
1745           return rec_message;
1746         }
1747       rec_message = rec_message->next;
1748     }
1749   return NULL;
1750 }
1751
1752
1753 /**
1754  * Function to dispose the fragments received for a message and the message
1755  * @param plugin pointer to the plugin struct
1756  * @param rec_message pointer to the struct holding the message which should be freed
1757  */
1758 static void
1759 free_receive_message(struct Plugin* plugin,
1760     struct Receive_Message_Queue * rx_message)
1761 {
1762   GNUNET_assert(rx_message !=NULL);
1763   struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1764   struct Receive_Fragment_Queue * rec_queue2;
1765
1766   while (rec_queue != NULL)
1767     {
1768       rec_queue2 = rec_queue;
1769       rec_queue = rec_queue->next;
1770       GNUNET_free(rec_queue2);
1771     }
1772
1773   GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
1774
1775   GNUNET_assert(plugin->pending_receive_messages > 0);
1776   GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
1777
1778   plugin->pending_receive_messages--;
1779   rx_message->session->fragment_messages_in_count--;
1780   GNUNET_free(rx_message);
1781 }
1782
1783
1784 /**
1785  * Function that can be used to force the plugin to disconnect
1786  * from the given peer and cancel all previous transmissions
1787  * (and their continuation).
1788  *
1789  * @param cls closure
1790  * @param target peer from which to disconnect
1791  */
1792 static void
1793 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1794 {
1795   struct Plugin *plugin = cls;
1796   struct Sessionqueue * queue = plugin->sessions;
1797   struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1798   struct PendingMessage * pm = NULL;
1799   struct FragmentMessage * fm;
1800   struct Receive_Message_Queue * receive_queue;
1801
1802   // just look at all the session for the needed one
1803   while (queue != NULL)
1804     {
1805       // content is never NULL
1806       GNUNET_assert (queue->content != NULL);
1807       if (memcmp(target, &(queue->content->target),
1808           sizeof(struct GNUNET_PeerIdentity)) == 0)
1809         {
1810           //session found
1811           //is this session pending for send
1812           while (pendingsession != NULL)
1813             {
1814               if (pendingsession->content == queue->content)
1815                 {
1816                   plugin->pendingsessions--;
1817                   GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1818                       plugin->pending_Sessions_tail, pendingsession);
1819                   GNUNET_free(pendingsession);
1820                   break;
1821                 }
1822               pendingsession = pendingsession->next;
1823             }
1824
1825           //is something of this session in the fragment queue?
1826           fm = get_fragment_message_from_session(queue->content);
1827           while (fm != NULL)
1828             {
1829               free_fragment_message(plugin, fm);
1830               fm = get_fragment_message_from_session(queue->content);
1831             }
1832           check_next_fragment_timeout(plugin);
1833
1834           //dispose all received fragments
1835           receive_queue = get_receive_message_from_session(plugin,
1836               queue->content);
1837           while (receive_queue != NULL)
1838             {
1839               free_receive_message(plugin, receive_queue);
1840               receive_queue = get_receive_message_from_session(plugin,
1841                   queue->content);
1842             }
1843
1844           // remove PendingMessage
1845           pm = queue->content->pending_message;
1846           if (pm != NULL)
1847             {
1848               GNUNET_free_non_null(pm->msg);
1849               GNUNET_free(pm);
1850             }
1851
1852           GNUNET_free(queue->content);
1853           GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1854           GNUNET_free(queue);
1855           plugin->session_count--;
1856
1857           return;
1858         }
1859       // try next
1860       queue = queue->next;
1861     }
1862 }
1863
1864 /**
1865  * Convert the transports address to a nice, human-readable
1866  * format.
1867  *
1868  * @param cls closure
1869  * @param type name of the transport that generated the address
1870  * @param addr one of the addresses of the host, NULL for the last address
1871  *        the specific address format depends on the transport
1872  * @param addrlen length of the address
1873  * @param numeric should (IP) addresses be displayed in numeric form?
1874  * @param timeout after how long should we give up?
1875  * @param asc function to call on each string
1876  * @param asc_cls closure for asc
1877  */
1878 static void
1879 wlan_plugin_address_pretty_printer(void *cls, const char *type,
1880     const void *addr, size_t addrlen, int numeric,
1881     struct GNUNET_TIME_Relative timeout,
1882     GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
1883 {
1884   char ret[92];
1885   const unsigned char * input;
1886
1887   //GNUNET_assert(cls !=NULL);
1888   if (addrlen != 6)
1889     {
1890       /* invalid address (MAC addresses have 6 bytes) */
1891       GNUNET_break (0);
1892       asc(asc_cls, NULL);
1893       return;
1894     }
1895   input = (const unsigned char*) addr;
1896   GNUNET_snprintf(ret, sizeof(ret),
1897       "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
1898       input[0], input[1], input[2], input[3], input[4], input[5]);
1899   asc(asc_cls, ret);
1900 }
1901
1902
1903
1904 /**
1905  * Function called for a quick conversion of the binary address to
1906  * a numeric address.  Note that the caller must not free the 
1907  * address and that the next call to this function is allowed
1908  * to override the address again.
1909  *
1910  * @param cls closure
1911  * @param addr binary address
1912  * @param addrlen length of the address
1913  * @return string representing the same address 
1914  */
1915 static const char*
1916 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
1917 {
1918   static char ret[40];
1919   const struct MacAddress *mac;
1920
1921   if (addrlen != sizeof(struct MacAddress))
1922     {
1923       GNUNET_break (0);
1924       return NULL;
1925     }
1926   mac = addr;
1927   GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
1928       PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
1929       mac->mac[4], mac->mac[5]);
1930   return ret;
1931 }
1932
1933 /**
1934  * function to check if bitfield is representation of fragments of the message
1935  * @param rec_message message to check
1936  */
1937
1938 void
1939 check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
1940 {
1941   uint64_t checkfragments = 0;
1942   struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
1943
1944   while (rec_queue != NULL)
1945     {
1946       setBit((char*) &checkfragments, rec_queue->num);
1947       rec_queue = rec_queue->next;
1948
1949     }
1950   GNUNET_assert(checkfragments == rec_message->received_fragments);
1951 }
1952
1953 /**
1954  * Function to test if fragment number already exists in the fragments received
1955  *
1956  * @param rec_message message this fragment belongs to
1957  * @param fh Fragmentheader of the fragment
1958  * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
1959  */
1960
1961 static const int
1962 is_double_msg(struct Receive_Message_Queue * rec_message,
1963     struct FragmentationHeader * fh)
1964 {
1965   //test if bitfield is okay
1966 #if DEBUG_wlan
1967   check_message_fragment_bitfield(rec_message);
1968 #endif
1969
1970   return testBit((char *) &rec_message->received_fragments, ntohs(
1971       fh->fragment_off_or_num));
1972
1973 }
1974
1975 /**
1976  * Function to insert a fragment in a queue of a message
1977  * @param session session the fragment belongs to
1978  * @param rec_queue fragment to add
1979  */
1980
1981 static void
1982 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
1983     struct Receive_Fragment_Queue * rx_frag)
1984 {
1985   GNUNET_assert(rx_message != NULL);
1986   GNUNET_assert(rx_frag != NULL);
1987
1988   struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
1989   struct WlanHeader * wlanheader = NULL;
1990
1991
1992   //this is the first fragment of the message (fragment id 0)
1993   if (rx_frag->num == 0)
1994     {
1995       wlanheader = (struct WlanHeader *) rx_frag->msg;
1996       rx_message->rec_size = ntohs(wlanheader->header.size);
1997     }
1998
1999   //sort into list
2000   while (rx_frag2 != NULL)
2001     {
2002       if (rx_frag2->num > rx_frag->num)
2003         {
2004           //next element number is grater than the current num
2005           GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2006           setBit((char *) &rx_message->received_fragments, rx_frag->num);
2007           return;
2008         }
2009       rx_frag2 = rx_frag2->next;
2010     }
2011
2012   //no element has a grater number
2013   GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2014
2015   setBit((char *) &rx_message->received_fragments, rx_frag->num);
2016 }
2017
2018
2019
2020
2021
2022 /**
2023  * handels the data after all fragments are put together
2024  * @param plugin
2025  * @param session_light
2026  * @param hdr pointer to the data
2027  */
2028 static void
2029 wlan_data_massage_handler(struct Plugin * plugin,
2030     struct Session_light * session_light,
2031     const struct GNUNET_MessageHeader * hdr)
2032 {
2033   struct WlanHeader * wlanheader = NULL;
2034   struct Session * session = NULL;
2035   const char * tempmsg = NULL;
2036   const struct GNUNET_MessageHeader * temp_hdr = NULL;
2037   struct GNUNET_PeerIdentity tmptarget;
2038
2039   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2040     {
2041
2042 #if DEBUG_wlan
2043       GNUNET_log(
2044           GNUNET_ERROR_TYPE_DEBUG,
2045           "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2046           ntohs(hdr->size));
2047 #endif
2048
2049       if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2050           + sizeof(struct GNUNET_MessageHeader))
2051         {
2052           //packet not big enought
2053           return;
2054         }
2055
2056       GNUNET_assert(session_light != NULL);
2057       if (session_light->session == NULL)
2058         {
2059           session_light->session = search_session(plugin, &session_light->addr);
2060         }
2061       session = session_light->session;
2062       wlanheader = (struct WlanHeader *) hdr;
2063
2064       tempmsg = (char*) &wlanheader[1];
2065       temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2066
2067       if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2068           wlanheader->crc))
2069         {
2070           //wrong crc, dispose message
2071           GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2072               "Wlan message Header crc was wrong\n");
2073           return;
2074         }
2075
2076       //if not in session list
2077       if (session == NULL)
2078         {
2079 #if DEBUG_wlan
2080           GNUNET_log(
2081               GNUNET_ERROR_TYPE_DEBUG,
2082               "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2083               ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2084               sizeof(struct WlanHeader));
2085 #endif
2086           //try if it is a hello message
2087           if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2088               + sizeof(struct WlanHeader))
2089             {
2090               if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2091                 {
2092                   if (GNUNET_HELLO_get_id(
2093                       (const struct GNUNET_HELLO_Message *) temp_hdr,
2094                       &tmptarget) == GNUNET_OK)
2095                     {
2096                       session = create_session(plugin, &session_light->addr);
2097                       session_light->session = session;
2098                       memcpy(&session->target, &tmptarget,
2099                           sizeof(struct GNUNET_PeerIdentity));
2100                     }
2101                   else
2102                     {
2103                       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2104                           "WLAN client not in session list and hello message not okay\n");
2105                       return;
2106                     }
2107
2108                 }
2109               else
2110                 {
2111                   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2112                       "WLAN client not in session list and not a hello message\n");
2113                   return;
2114                 }
2115             }
2116           else
2117             {
2118               GNUNET_log(
2119                   GNUNET_ERROR_TYPE_WARNING,
2120                   "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2121                   ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2122                   sizeof(struct WlanHeader));
2123               return;
2124             }
2125         }
2126
2127       //"receive" the message
2128
2129
2130       GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2131           (const char *) temp_hdr,
2132           ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2133
2134       return;
2135     }
2136   else
2137     {
2138       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2139           "wlan_data_massage_handler got wrong message type\n");
2140       return;
2141     }
2142 }
2143
2144
2145
2146 /**
2147  * Function to check if all fragments of a message have been received
2148  * @param plugin the plugin handle
2149  * @param session_light information of the message sender
2150  * @param session session the message belongs to
2151  * @param rec_message pointer to the message that should be checked
2152  */
2153
2154 static void
2155 check_rec_finished_msg(struct Plugin* plugin,
2156     struct Session_light * session_light, struct Session * session,
2157     struct Receive_Message_Queue * rx_message)
2158 {
2159   GNUNET_assert(rx_message !=NULL);
2160
2161   struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2162   int packetsize = rx_message->rec_size;
2163   int sum = 0;
2164   int aktnum = 0;
2165   uint64_t bitfield = 0;
2166   char * msg;
2167
2168   //check if first fragment is present
2169   if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2170     {
2171       return;
2172     }
2173   // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2174   else if (packetsize < sizeof(struct WlanHeader)
2175       + sizeof(struct GNUNET_MessageHeader))
2176     {
2177 #if DEBUG_wlan
2178       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2179 #endif
2180       free_receive_message(plugin, rx_message);
2181       return;
2182     }
2183
2184 #if DEBUG_wlan
2185   check_message_fragment_bitfield(rx_message);
2186 #endif
2187
2188   //  if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2189   //    {
2190   bitfield = ~bitfield;
2191   bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2192   if (rx_message->received_fragments == bitfield)
2193     {
2194
2195       while (rx_frag != NULL)
2196         {
2197           sum += rx_frag->size;
2198           rx_frag = rx_frag->next;
2199         }
2200       //sum should always be smaller or equal of
2201       GNUNET_assert(sum <= packetsize);
2202       if (sum == packetsize)
2203         {
2204
2205 #if DEBUG_wlan
2206           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2207               "check_rec_finished_msg: A message for %p is complete\n", session);
2208 #endif
2209
2210           //TODO use mst
2211           //copy fragments together
2212           msg = GNUNET_malloc(packetsize);
2213           rx_frag = rx_message->frag_head;
2214           aktnum = 0;
2215           while (rx_frag != NULL)
2216             {
2217               //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2218               memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2219               aktnum += rx_frag->size;
2220               rx_frag = rx_frag->next;
2221             }
2222
2223           free_receive_message(plugin, rx_message);
2224           //call wlan_process_helper to process the message
2225           wlan_data_massage_handler(plugin, session_light,
2226               (struct GNUNET_MessageHeader*) msg);
2227           //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2228
2229           GNUNET_free(msg);
2230         }
2231     }
2232   //    }
2233 }
2234
2235 static void
2236 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2237 {
2238
2239   GNUNET_assert(client != NULL);
2240   GNUNET_assert(cls != NULL);
2241   struct Session * session = (struct Session *) client;
2242   struct Plugin * plugin = (struct Plugin *) cls;
2243
2244   struct GNUNET_TRANSPORT_ATS_Information distance[2];
2245   distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2246   distance[0].value = htonl(1);
2247   distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2248   distance[1].value = htonl(0);
2249
2250 #if DEBUG_wlan
2251   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2252       "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2253       wlan_plugin_address_to_string(NULL, session->addr, 6), htons(hdr->size));
2254 #endif
2255
2256   plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2257                        (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2258                        (const char*) &session->addr, sizeof(session->addr));
2259 }
2260
2261 /**
2262  * function to add an ack to send it for a received fragment
2263  * @param plugin pointer to the global plugin structure
2264  * @param session pointer to the session this ack belongs to
2265  * @param bitfield bitfield to send
2266  * @param fh pointer to the fragmentation header which we would like to acknolage
2267  */
2268
2269 void
2270 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2271     uint64_t bitfield, struct FragmentationHeader * fh)
2272 {
2273   struct AckSendQueue * ack;
2274
2275   GNUNET_assert(plugin != NULL);
2276   GNUNET_assert(session != NULL);
2277   GNUNET_assert(fh != NULL);
2278
2279   ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2280   ack->fragments_field = bitfield;
2281   ack->message_id = ntohl(fh->message_id);
2282   ack->session = session;
2283
2284   GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2285       plugin->ack_send_queue_tail, ack);
2286
2287 }
2288
2289 /**
2290  * function to get the receive message from the message id and the session
2291  * @param plugin pointer to the plugin struct
2292  * @param session session this fragment belongs to
2293  * @param message_id id of the message
2294  */
2295
2296 struct Receive_Message_Queue *
2297 get_receive_message(struct Plugin * plugin, struct Session * session,
2298     uint32_t message_id)
2299 {
2300   struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2301   while (rec_message != NULL)
2302     {
2303       if ((rec_message->message_id_in == message_id) && (rec_message->session
2304           == session))
2305         {
2306           return rec_message;
2307         }
2308       rec_message = rec_message->next;
2309     }
2310   return NULL;
2311 }
2312
2313
2314
2315 /**
2316  * function to insert a received fragment into the right fragment queue of the right message
2317  * @param plugin pointer to the plugin struct
2318  * @param session_light pointer to the session_light struct of this message
2319  * @param session session this fragment belongs to
2320  * @param fh pointer to the header of the fragment
2321  * @return new fragment bitfield for the message
2322  */
2323
2324 uint64_t
2325 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2326     struct Session_light * session_light, struct Session * session,
2327     struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2328 {
2329   struct Receive_Fragment_Queue * rx_frag = NULL;
2330   struct Receive_Message_Queue * rx_message;
2331   const char * tempmsg = (char*) &fh[1];
2332   uint64_t retval = 0;
2333
2334   //TODO fragments do not timeout
2335   //check if message_id is right or it is a new msg
2336   GNUNET_assert(fh != NULL);
2337
2338   rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2339
2340   if (rx_message == NULL)
2341     {
2342       if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2343         {
2344
2345           //new message incoming
2346           rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2347           rx_message->message_id_in = ntohl(fh->message_id);
2348           rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2349           rx_message->session = session;
2350           rx_message->timeout = GNUNET_TIME_absolute_add(
2351               GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
2352           rx_message->received_fragments = 0;
2353
2354           GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2355
2356           session->fragment_messages_in_count++;
2357           plugin->pending_receive_messages++;
2358
2359 #if DEBUG_wlan
2360           GNUNET_log(
2361               GNUNET_ERROR_TYPE_DEBUG,
2362               "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2363               rx_message->message_id_in, session->fragment_messages_in_count,
2364               plugin->pending_receive_messages);
2365 #endif
2366         }
2367       else
2368         {
2369
2370           GNUNET_log(
2371               GNUNET_ERROR_TYPE_INFO,
2372               "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
2373           setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2374           return retval;
2375         }
2376     }
2377
2378   if (is_double_msg(rx_message, fh) != GNUNET_YES)
2379     {
2380
2381
2382       //report size
2383       rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2384           ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2385       rx_frag->size = ntohs(fh->header.size)
2386           - sizeof(struct FragmentationHeader);
2387       rx_frag->num = ntohs(fh->fragment_off_or_num);
2388       rx_frag->msg = (char*) &(rx_frag[1]);
2389       //copy msg to buffer
2390       memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2391       memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2392       insert_fragment_in_queue(rx_message, rx_frag);
2393       //save bitfield
2394       retval = rx_message->received_fragments;
2395
2396 #if DEBUG_wlan
2397       GNUNET_log(
2398           GNUNET_ERROR_TYPE_DEBUG,
2399           "New fragment:  size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2400           rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2401           rx_message->received_fragments, session);
2402 #endif
2403
2404       check_rec_finished_msg(plugin, session_light, session, rx_message);
2405     }
2406   else
2407     {
2408       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2409       retval = rx_message->received_fragments;
2410
2411     }
2412   return retval;
2413
2414 }
2415
2416 /**
2417  * Function used for to process the data received from the wlan interface
2418  *
2419  * @param cls the plugin handle
2420  * @param session_light FIXME: document
2421  * @param hdr hdr of the GNUNET_MessageHeader
2422  */
2423 static void
2424 wlan_data_helper(void *cls, struct Session_light * session_light,
2425     const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2426 {
2427   struct Plugin *plugin = cls;
2428   struct Session * session = NULL;
2429
2430   struct FragmentationHeader * fh = NULL;
2431   struct FragmentationAckHeader * fah = NULL;
2432   struct FragmentMessage * fm = NULL;
2433
2434   const char * tempmsg = NULL;
2435
2436   uint64_t fragment_bitfield = 0;
2437
2438   //ADVERTISEMENT
2439   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2440     {
2441
2442       //TODO better DOS protection, error handling
2443       //TODO test first than create session
2444       GNUNET_assert(session_light != NULL);
2445
2446 #if DEBUG_wlan
2447       GNUNET_log(
2448           GNUNET_ERROR_TYPE_DEBUG,
2449           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2450           ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2451               session_light->addr, 6));
2452 #endif
2453
2454       if (session_light->session == NULL)
2455         {
2456           session_light->session = get_Session(plugin, &session_light->addr);
2457         }
2458       GNUNET_assert(GNUNET_HELLO_get_id(
2459               (const struct GNUNET_HELLO_Message *) &hdr[1],
2460               &(session_light->session->target) ) != GNUNET_SYSERR);
2461
2462     }
2463
2464   //FRAGMENT
2465   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2466     {
2467
2468       GNUNET_assert(session_light != NULL);
2469       if (session_light->session == NULL)
2470         {
2471           session_light->session = search_session(plugin, &session_light->addr);
2472         }
2473       session = session_light->session;
2474
2475       fh = (struct FragmentationHeader *) hdr;
2476       tempmsg = (char*) &fh[1];
2477
2478 #if DEBUG_wlan
2479       GNUNET_log(
2480           GNUNET_ERROR_TYPE_DEBUG,
2481           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2482           ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2483               hdr->size), wlan_plugin_address_to_string(NULL,
2484               session_light->addr, 6));
2485 #endif
2486
2487       if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2488         {
2489           //wrong crc, dispose message
2490           GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2491           return;
2492         }
2493
2494       //if in the session list
2495       if (session != NULL)
2496         {
2497           fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2498               session_light, session, fh, rxinfo);
2499         }
2500       else
2501         {
2502           // new session
2503           GNUNET_log(
2504               GNUNET_ERROR_TYPE_INFO,
2505               "WLAN client not in session list, fragment num %u, message id %u\n",
2506               ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2507           wlan_data_massage_handler(plugin, session_light,
2508               (struct GNUNET_MessageHeader *) tempmsg);
2509           session = session_light->session;
2510           //test if a session was created
2511           if (session == NULL)
2512             {
2513               return;
2514             }
2515           setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2516         }
2517
2518       add_ack_for_send(plugin, session, fragment_bitfield, fh);
2519       check_next_fragment_timeout(plugin);
2520
2521     }
2522
2523   //ACK
2524   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2525     {
2526
2527 #if DEBUG_wlan
2528       GNUNET_log(
2529           GNUNET_ERROR_TYPE_DEBUG,
2530           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2531           ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2532               session_light->addr, 6));
2533 #endif
2534
2535       GNUNET_assert(session_light != NULL);
2536       if (session_light->session == NULL)
2537         {
2538           session_light->session = search_session(plugin, &session_light->addr);
2539           GNUNET_assert(session_light->session != NULL);
2540         }
2541       session = session_light->session;
2542       fah = (struct FragmentationAckHeader *) hdr;
2543       fm = get_fragment_message_from_session_and_id(session, ntohl(
2544           fah->message_id));
2545       if (fm != NULL)
2546         {
2547
2548           fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(fah->fragment_field);
2549           check_finished_fragment(plugin, fm);
2550         }
2551       else
2552         {
2553           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2554               "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2555                   fah->message_id));
2556           return;
2557         }
2558
2559     }
2560   else
2561     {
2562       // TODO Wrong data?
2563       GNUNET_log(
2564           GNUNET_ERROR_TYPE_INFO,
2565           "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2566           ntohs(hdr->type), ntohs(hdr->size));
2567       GNUNET_assert(0);
2568       return;
2569     }
2570
2571 #if 0
2572   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2573       "Helper finished\n");
2574 #endif
2575
2576 }
2577
2578 const char *
2579 macprinter(const u_int8_t * mac)
2580 {
2581   static char macstr[20];
2582
2583   GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2584       mac[2], mac[3], mac[4], mac[5]);
2585   return macstr;
2586 }
2587
2588 /**
2589  * Function used for to process the data from the suid process
2590  *
2591  * @param cls the plugin handle
2592  * @param client client that send the data (not used)
2593  * @param hdr header of the GNUNET_MessageHeader
2594  */
2595 static void
2596 wlan_process_helper(void *cls, void *client,
2597     const struct GNUNET_MessageHeader *hdr)
2598 {
2599   struct Plugin *plugin = cls;
2600   struct ieee80211_frame * wlanIeeeHeader = NULL;
2601   struct Session_light * session_light = NULL;
2602   struct Radiotap_rx * rxinfo;
2603   const struct GNUNET_MessageHeader * temp_hdr = NULL;
2604
2605   int datasize = 0;
2606   int pos = 0;
2607
2608   switch (ntohs(hdr->type))
2609     {
2610   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2611 #if DEBUG_wlan
2612     GNUNET_log(
2613         GNUNET_ERROR_TYPE_DEBUG,
2614         "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2615         ntohs(hdr->size));
2616 #endif
2617
2618     //call wlan_process_helper with the message inside, later with wlan: analyze signal
2619     if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2620         + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2621       {
2622 #if DEBUG_wlan
2623         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2624             "Size of packet is too small; size: %u min size: %u\n", ntohs(
2625                 hdr->size), sizeof(struct ieee80211_frame)
2626                 + sizeof(struct GNUNET_MessageHeader));
2627 #endif
2628         GNUNET_break (0);
2629         /* FIXME: restart SUID process */
2630         return;
2631       }
2632     rxinfo = (struct Radiotap_rx *) &hdr[1];
2633     wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2634
2635     //process only if it is an broadcast or for this computer both with the gnunet bssid
2636
2637     //check for bssid
2638     if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid, sizeof(struct MacAddress))
2639         == 0)
2640       {
2641         //check for broadcast or mac
2642         if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2643             sizeof(struct MacAddress) == 0) || memcmp(
2644             &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2645             sizeof(struct MacAddress)) == 0)
2646           {
2647
2648             // process the inner data
2649
2650
2651             datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2652                 - sizeof(struct GNUNET_MessageHeader)
2653                 - sizeof(struct Radiotap_rx);
2654
2655             session_light = GNUNET_malloc(sizeof(struct Session_light));
2656             memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2657                    sizeof(struct MacAddress));
2658             //session_light->session = search_session(plugin,session_light->addr);
2659
2660             pos = 0;
2661             temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
2662             while (pos < datasize)
2663               {
2664                 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2665                     + pos;
2666
2667                 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2668                 pos += ntohs(temp_hdr->size);
2669
2670               }
2671
2672             //clean up
2673             GNUNET_free(session_light);
2674           }
2675         else
2676           {
2677 #if DEBUG_wlan
2678             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2679                 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2680                     wlanIeeeHeader->i_addr1));
2681 #endif
2682           }
2683       }
2684     else
2685       {
2686 #if DEBUG_wlan
2687         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2688             "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2689                 wlanIeeeHeader->i_addr2));
2690 #endif
2691       }
2692     break;
2693   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2694     //TODO more control messages
2695     //TODO use struct wlan_helper_control
2696     if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2697       {
2698         GNUNET_break (0);
2699         /* FIXME: restart SUID process */
2700         return;
2701       }
2702     memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2703 #if DEBUG_wlan
2704     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2705         "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2706         wlan_plugin_address_to_string(cls, &plugin->mac_address,
2707             sizeof(struct MacAddress)));
2708 #endif
2709     plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2710         sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2711     break;
2712   default:
2713     GNUNET_break (0);
2714     return;
2715     }
2716 }
2717
2718 /**
2719  * We have been notified that wlan-helper has written something to stdout.
2720  * Handle the output, then reschedule this function to be called again once
2721  * more is available.
2722  *
2723  * @param cls the plugin handle
2724  * @param tc the scheduling context
2725  */
2726 static void
2727 wlan_plugin_helper_read(void *cls,
2728     const struct GNUNET_SCHEDULER_TaskContext *tc)
2729 {
2730   struct Plugin *plugin = cls;
2731   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2732
2733   /*
2734    #if DEBUG_wlan
2735    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2736    "Start reading from STDIN\n");
2737    #endif
2738    */
2739   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2740     return;
2741
2742   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2743   ssize_t bytes;
2744
2745   bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2746       sizeof(mybuf));
2747   if (bytes <= 0)
2748     {
2749 #if DEBUG_wlan
2750       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2751           _("Finished reading from wlan-helper stdout with code: %d\n"),
2752           bytes);
2753 #endif
2754       return;
2755     }
2756   GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2757       GNUNET_NO, GNUNET_NO);
2758
2759   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2760   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2761       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2762       &wlan_plugin_helper_read, plugin);
2763 }
2764
2765 /**
2766  * Start the gnunet-wlan-helper process.
2767  *
2768  * @param plugin the transport plugin
2769  * @param testmode should we use the dummy driver for testing?
2770  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2771  */
2772 static int
2773 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2774 {
2775   const char * filename = "gnunet-transport-wlan-helper";
2776   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2777   if (plugin->server_stdout == NULL)
2778     return GNUNET_SYSERR;
2779
2780   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2781   if (plugin->server_stdin == NULL)
2782     return GNUNET_SYSERR;
2783
2784 #if DEBUG_wlan
2785   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2786       "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2787       plugin->interface, testmode);
2788 #endif
2789   /* Start the server process */
2790
2791   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2792       plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2793           == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2794   if (plugin->server_proc == NULL)
2795     {
2796 #if DEBUG_wlan
2797       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2798           "Failed to start gnunet-wlan-helper process\n");
2799 #endif
2800       return GNUNET_SYSERR;
2801     }
2802
2803   /* Close the write end of the read pipe */
2804   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2805
2806   /* Close the read end of the write pipe */
2807   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2808
2809   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2810       GNUNET_DISK_PIPE_END_READ);
2811   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2812       GNUNET_DISK_PIPE_END_WRITE);
2813
2814   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2815
2816 #if DEBUG_wlan
2817   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2818       "Adding server_read_task for the wlan-helper\n");
2819 #endif
2820
2821   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2822       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2823       &wlan_plugin_helper_read, plugin);
2824
2825   return GNUNET_YES;
2826 }
2827
2828 /**
2829  * Exit point from the plugin.
2830  * @param cls pointer to the api struct
2831  */
2832
2833 //FIXME cleanup
2834 void *
2835 libgnunet_plugin_transport_wlan_done(void *cls)
2836 {
2837   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2838   struct Plugin *plugin = api->cls;
2839
2840 #if DEBUG_wlan
2841   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2842       "libgnunet_plugin_transport_wlan_done started\n");
2843 #endif
2844
2845   GNUNET_assert(cls !=NULL);
2846
2847   if (plugin->suid_tokenizer != NULL)
2848     GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2849
2850   if (plugin->data_tokenizer != NULL)
2851     GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
2852
2853   GNUNET_free_non_null(plugin->interface);
2854   GNUNET_free (plugin);
2855   GNUNET_free (api);
2856   return NULL;
2857 }
2858
2859 /**
2860  * Entry point for the plugin.
2861  *
2862  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2863  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2864  */
2865 void *
2866 libgnunet_plugin_transport_wlan_init(void *cls)
2867 {
2868   //struct GNUNET_SERVICE_Context *service;
2869   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2870   struct GNUNET_TRANSPORT_PluginFunctions *api;
2871   struct Plugin *plugin;
2872   static unsigned long long testmode = 0;
2873
2874   GNUNET_assert(cls !=NULL);
2875
2876   plugin = GNUNET_malloc (sizeof (struct Plugin));
2877   plugin->env = env;
2878   plugin->pendingsessions = 0;
2879   plugin->session_count = 0;
2880   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2881   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2882   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2883
2884   plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
2885       plugin);
2886
2887   plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
2888
2889   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2890   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2891
2892   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2893   api->cls = plugin;
2894   api->send = &wlan_plugin_send;
2895   api->disconnect = &wlan_plugin_disconnect;
2896   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2897   api->check_address = &wlan_plugin_address_suggested;
2898   api->address_to_string = &wlan_plugin_address_to_string;
2899
2900   //read config
2901
2902   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
2903     {
2904       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
2905           "transport-wlan", "TESTMODE", &testmode))
2906         testmode = 0; //default value
2907     }
2908
2909   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
2910     {
2911       if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
2912           "INTERFACE", &(plugin->interface)) != GNUNET_YES)
2913         {
2914           libgnunet_plugin_transport_wlan_done(api);
2915           return NULL;
2916         }
2917     }
2918
2919   //start the plugin
2920   set_next_beacon_time(plugin);
2921
2922   wlan_transport_start_wlan_helper(plugin, testmode);
2923
2924 #if DEBUG_wlan
2925   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
2926 #endif
2927
2928   return api;
2929 }
2930
2931 /* end of plugin_transport_wlan.c */