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