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