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