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