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