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