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