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