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