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