removing legacy send functions from plugins and renaming new send function
[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_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_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 /**
2196  * Creates a new outbound session the transport service will use to send data to the
2197  * peer
2198  *
2199  * @param cls the plugin
2200  * @param address the address
2201  * @return the session or NULL of max connections exceeded
2202  */
2203
2204 static struct Session *
2205 wlan_plugin_get_session (void *cls,
2206                   const struct GNUNET_HELLO_Address *address)
2207 {
2208   struct Plugin *plugin = cls;
2209   struct Session * s = NULL;
2210
2211   GNUNET_assert (plugin != NULL);
2212   GNUNET_assert (address != NULL);
2213
2214   if (GNUNET_OK == wlan_plugin_address_suggested (plugin,
2215             address->address,
2216             address->address_length))
2217   {
2218     s = get_session (plugin, address->address, &address->peer);
2219   }
2220   else
2221   {
2222     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2223                      _("Wlan Address len %d is wrong\n"), address->address_length);
2224     return s;
2225   }
2226
2227   return s;
2228 }
2229
2230 /**
2231  * Function that can be used by the transport service to transmit
2232  * a message using the plugin.   Note that in the case of a
2233  * peer disconnecting, the continuation MUST be called
2234  * prior to the disconnect notification itself.  This function
2235  * will be called with this peer's HELLO message to initiate
2236  * a fresh connection to another peer.
2237  *
2238  * @param cls closure
2239  * @param session which session must be used
2240  * @param msgbuf the message to transmit
2241  * @param msgbuf_size number of bytes in 'msgbuf'
2242  * @param priority how important is the message (most plugins will
2243  *                 ignore message priority and just FIFO)
2244  * @param to how long to wait at most for the transmission (does not
2245  *                require plugins to discard the message after the timeout,
2246  *                just advisory for the desired delay; most plugins will ignore
2247  *                this as well)
2248  * @param cont continuation to call once the message has
2249  *        been transmitted (or if the transport is ready
2250  *        for the next transmission call; or if the
2251  *        peer disconnected...); can be NULL
2252  * @param cont_cls closure for cont
2253  * @return number of bytes used (on the physical network, with overheads);
2254  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
2255  *         and does NOT mean that the message was not transmitted (DV)
2256  */
2257 static ssize_t
2258 wlan_plugin_send (void *cls,
2259                   struct Session *session,
2260                   const char *msgbuf, size_t msgbuf_size,
2261                   unsigned int priority,
2262                   struct GNUNET_TIME_Relative to,
2263                   GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
2264 {
2265   struct Plugin *plugin = cls;
2266   struct PendingMessage *newmsg;
2267   struct WlanHeader *wlanheader;
2268
2269   GNUNET_assert (plugin != NULL);
2270   GNUNET_assert (session != NULL);
2271   GNUNET_assert (msgbuf_size > 0);
2272
2273   //queue message:
2274
2275   //queue message in session
2276   //test if there is no other message in the "queue"
2277   //FIXME: to many send requests
2278   if (session->pending_message_head != NULL)
2279   {
2280     newmsg = session->pending_message_head;
2281     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2282                      "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",
2283                      GNUNET_TIME_absolute_get_remaining (newmsg->
2284                                                          timeout).rel_value,
2285                      session->mac->fragment_messages_out_count);
2286   }
2287
2288   newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
2289   newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
2290   wlanheader = newmsg->msg;
2291   //copy msg to buffer, not fragmented / segmented yet, but with message header
2292   wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
2293   wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
2294   memcpy (&(wlanheader->target), &session->target, sizeof (struct GNUNET_PeerIdentity));
2295   memcpy (&(wlanheader->source), plugin->env->my_identity,
2296           sizeof (struct GNUNET_PeerIdentity));
2297   wlanheader->crc = 0;
2298   memcpy (&wlanheader[1], msgbuf, msgbuf_size);
2299   wlanheader->crc =
2300       htonl (GNUNET_CRYPTO_crc32_n
2301              ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
2302
2303   newmsg->transmit_cont = cont;
2304   newmsg->transmit_cont_cls = cont_cls;
2305   newmsg->timeout = GNUNET_TIME_relative_to_absolute (to);
2306
2307   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
2308
2309   newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
2310
2311   GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
2312                                     session->pending_message_tail, newmsg);
2313
2314 #if DEBUG_wlan
2315   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2316                    "New message for %p with size (incl wlan header) %u added\n",
2317                    session, newmsg->message_size);
2318 #endif
2319 #if DEBUG_wlan_msg_dump > 1
2320   hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
2321 #endif
2322   //queue session
2323   queue_session (plugin, session);
2324
2325   check_fragment_queue (plugin);
2326   //FIXME not the correct size
2327   return msgbuf_size;
2328 }
2329
2330
2331 /**
2332  * function to free a mac endpoint
2333  * @param plugin pointer to the plugin struct
2334  * @param endpoint pointer to the MacEndpoint to free
2335  */
2336 static void
2337 free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
2338 {
2339   struct Sessionqueue *sessions;
2340   struct Sessionqueue *sessions_next;
2341
2342   GNUNET_assert (endpoint != NULL);
2343
2344   sessions = endpoint->sessions_head;
2345   while (sessions != NULL)
2346   {
2347     sessions_next = sessions->next;
2348     free_session (plugin, sessions, GNUNET_NO);
2349     sessions = sessions_next;
2350   }
2351
2352   GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
2353   if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2354   {
2355     GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
2356     endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2357   }
2358   plugin->mac_count--;
2359   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2360                          plugin->mac_count, GNUNET_NO);
2361   GNUNET_free (endpoint);
2362
2363 }
2364
2365 /**
2366  * function to free a session
2367  * @param plugin pointer to the plugin
2368  * @param queue pointer to the sessionqueue element to free
2369  * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
2370  */
2371 static void
2372 free_session (struct Plugin *plugin, struct Sessionqueue *queue,
2373               int do_free_macendpoint)
2374 {
2375   struct Sessionqueue *pendingsession;
2376   struct Sessionqueue *pendingsession_tmp;
2377   struct PendingMessage *pm;
2378   struct MacEndpoint *endpoint;
2379   struct FragmentMessage *fm;
2380   struct FragmentMessage *fmnext;
2381   int check = 0;
2382
2383   GNUNET_assert (plugin != NULL);
2384   GNUNET_assert (queue != NULL);
2385   GNUNET_assert (queue->content != NULL);
2386
2387   //session found
2388   //is this session pending for send
2389   pendingsession = plugin->pending_Sessions_head;
2390   while (pendingsession != NULL)
2391   {
2392     pendingsession_tmp = pendingsession;
2393     pendingsession = pendingsession->next;
2394     GNUNET_assert (pendingsession_tmp->content != NULL);
2395     if (pendingsession_tmp->content == queue->content)
2396     {
2397       plugin->pendingsessions--;
2398       GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
2399                              plugin->pendingsessions, GNUNET_NO);
2400       GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2401                                    plugin->pending_Sessions_tail,
2402                                    pendingsession_tmp);
2403       GNUNET_free (pendingsession_tmp);
2404
2405       GNUNET_assert (check == 0);
2406       check = 1;
2407     }
2408   }
2409
2410   endpoint = queue->content->mac;
2411   fm = endpoint->sending_messages_head;
2412   while (fm != NULL)
2413   {
2414     fmnext = fm->next;
2415     if (fm->session == queue->content)
2416     {
2417       free_fragment_message (plugin, fm);
2418     }
2419     fm = fmnext;
2420   }
2421
2422   // remove PendingMessage
2423   pm = queue->content->pending_message_head;
2424   while (pm != NULL)
2425   {
2426     GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
2427                                  queue->content->pending_message_tail, pm);
2428     GNUNET_free (pm->msg);
2429     GNUNET_free (pm);
2430     pm = queue->content->pending_message_head;
2431   }
2432
2433   GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
2434                                queue);
2435   //Check that no ohter session on this endpoint for this session exits
2436   GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
2437                  NULL);
2438   if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
2439   {
2440     free_macendpoint (plugin, endpoint);
2441     //check if no endpoint with the same address exists
2442     GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
2443                    NULL);
2444   }
2445
2446   if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2447   {
2448     GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
2449     queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2450   }
2451   GNUNET_free (queue);
2452
2453   check_fragment_queue (plugin);
2454 }
2455
2456 /**
2457  * Function that can be used to force the plugin to disconnect
2458  * from the given peer and cancel all previous transmissions
2459  * (and their continuation).
2460  *
2461  * @param cls closure
2462  * @param target peer from which to disconnect
2463  */
2464 static void
2465 wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
2466 {
2467   struct Plugin *plugin = cls;
2468   struct Sessionqueue *queue;
2469   struct Sessionqueue *queue_next;
2470   struct MacEndpoint *endpoint = plugin->mac_head;
2471   struct MacEndpoint *endpoint_next;
2472
2473   // just look at all the session for the needed one
2474   while (endpoint != NULL)
2475   {
2476     queue = endpoint->sessions_head;
2477     endpoint_next = endpoint->next;
2478     while (queue != NULL)
2479     {
2480       // content is never NULL
2481       GNUNET_assert (queue->content != NULL);
2482       queue_next = queue->next;
2483       if (memcmp
2484           (target, &(queue->content->target),
2485            sizeof (struct GNUNET_PeerIdentity)) == 0)
2486       {
2487         free_session (plugin, queue, GNUNET_YES);
2488       }
2489       // try next
2490       queue = queue_next;
2491     }
2492     endpoint = endpoint_next;
2493   }
2494 }
2495
2496 /**
2497  * Convert the transports address to a nice, human-readable
2498  * format.
2499  *
2500  * @param cls closure
2501  * @param type name of the transport that generated the address
2502  * @param addr one of the addresses of the host, NULL for the last address
2503  *        the specific address format depends on the transport
2504  * @param addrlen length of the address
2505  * @param numeric should (IP) addresses be displayed in numeric form?
2506  * @param timeout after how long should we give up?
2507  * @param asc function to call on each string
2508  * @param asc_cls closure for asc
2509  */
2510 static void
2511 wlan_plugin_address_pretty_printer (void *cls, const char *type,
2512                                     const void *addr, size_t addrlen,
2513                                     int numeric,
2514                                     struct GNUNET_TIME_Relative timeout,
2515                                     GNUNET_TRANSPORT_AddressStringCallback asc,
2516                                     void *asc_cls)
2517 {
2518   char *ret;
2519   const unsigned char *input;
2520
2521   //GNUNET_assert(cls !=NULL);
2522   if (addrlen != sizeof (struct MacAddress))
2523   {
2524     /* invalid address (MAC addresses have 6 bytes) */
2525     //GNUNET_break (0);
2526 #if DEBUG_wlan
2527     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2528                      "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
2529                      addrlen);
2530 #endif
2531     asc (asc_cls, NULL);
2532     return;
2533   }
2534   input = (const unsigned char *) addr;
2535   GNUNET_asprintf (&ret,
2536                    "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
2537                    type, PROTOCOL_PREFIX, input[0], input[1], input[2],
2538                    input[3], input[4], input[5]);
2539 #if DEBUG_wlan
2540   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2541                    "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
2542                    addrlen, numeric, type, ret);
2543 #endif
2544   asc (asc_cls, ret);
2545   //only one mac address per plugin
2546   asc (asc_cls, NULL);
2547 }
2548
2549
2550
2551 /**
2552  * handels the data after all fragments are put together
2553  * @param cls macendpoint this messages belongs to
2554  * @param hdr pointer to the data
2555  */
2556 static void
2557 wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
2558 {
2559   struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
2560   struct Plugin *plugin = endpoint->plugin;
2561   struct WlanHeader *wlanheader;
2562   struct Session *session;
2563
2564   const struct GNUNET_MessageHeader *temp_hdr;
2565   struct GNUNET_PeerIdentity tmpsource;
2566   int crc;
2567
2568   GNUNET_assert (plugin != NULL);
2569
2570   if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2571   {
2572
2573 #if DEBUG_wlan
2574     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2575                      "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2576                      ntohs (hdr->size));
2577 #endif
2578
2579     if (ntohs (hdr->size) <
2580         sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
2581     {
2582       //packet not big enought
2583       return;
2584     }
2585
2586     GNUNET_STATISTICS_update (plugin->env->stats,
2587                               _("# wlan whole messages received"), 1,
2588                               GNUNET_NO);
2589     wlanheader = (struct WlanHeader *) hdr;
2590
2591     session = search_session (plugin, endpoint, &wlanheader->source);
2592
2593     temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2594     crc = ntohl (wlanheader->crc);
2595     wlanheader->crc = 0;
2596     if (GNUNET_CRYPTO_crc32_n
2597         ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
2598     {
2599       //wrong crc, dispose message
2600       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2601                        "Wlan message header crc was wrong: %u != %u\n",
2602                        GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
2603                                               ntohs (wlanheader->header.size)),
2604                        crc);
2605       hexdump ((void *) hdr, ntohs (hdr->size));
2606       return;
2607     }
2608
2609     //if not in session list
2610     if (session == NULL)
2611     {
2612 #if DEBUG_wlan
2613       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2614                        "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2615                        ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
2616                        sizeof (struct WlanHeader));
2617 #endif
2618       //try if it is a hello message
2619       if (ntohs (wlanheader->header.size) >=
2620           ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
2621       {
2622         if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2623         {
2624           if (GNUNET_HELLO_get_id
2625               ((const struct GNUNET_HELLO_Message *) temp_hdr,
2626                &tmpsource) == GNUNET_OK)
2627           {
2628             session = create_session (plugin, endpoint, &tmpsource);
2629           }
2630           else
2631           {
2632             GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2633                              "WLAN client not in session list and hello message is not okay\n");
2634             return;
2635           }
2636
2637         }
2638         else
2639         {
2640           GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2641                            "WLAN client not in session list and not a hello message\n");
2642           return;
2643         }
2644       }
2645       else
2646       {
2647         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2648                          "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2649                          ntohs (wlanheader->header.size),
2650                          ntohs (temp_hdr->size), sizeof (struct WlanHeader));
2651         return;
2652       }
2653     }
2654
2655     //"receive" the message
2656
2657     if (memcmp
2658         (&wlanheader->source, &session->target,
2659          sizeof (struct GNUNET_PeerIdentity)) != 0)
2660     {
2661       //wrong peer id
2662 #if DEBUG_wlan
2663       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2664                        "WLAN peer source id doesn't match packet peer source id: session %p\n",
2665                        session);
2666 #endif
2667       return;
2668     }
2669
2670     if (memcmp
2671         (&wlanheader->target, plugin->env->my_identity,
2672          sizeof (struct GNUNET_PeerIdentity)) != 0)
2673     {
2674       //wrong peer id
2675 #if DEBUG_wlan
2676       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2677                        "WLAN peer target id doesn't match our peer id: session %p\n",
2678                        session);
2679 #endif
2680       return;
2681     }
2682
2683     GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
2684                                (const char *) temp_hdr,
2685                                ntohs (hdr->size) - sizeof (struct WlanHeader),
2686                                GNUNET_YES, GNUNET_NO);
2687
2688     return;
2689   }
2690   else
2691   {
2692     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2693                      "wlan_data_message_handler got wrong message type: %u\n",
2694                      ntohs (hdr->size));
2695     return;
2696   }
2697 }
2698
2699 /**
2700  * function to process the a message, give it to the higher layer
2701  * @param cls pointer to the plugin
2702  * @param client pointer to the session this message belongs to
2703  * @param hdr start of the message
2704  */
2705 //TODO ATS informations
2706 static void
2707 process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2708 {
2709
2710   GNUNET_assert (client != NULL);
2711   GNUNET_assert (cls != NULL);
2712   struct Session *session = (struct Session *) client;
2713   struct Plugin *plugin = (struct Plugin *) cls;
2714   struct GNUNET_ATS_Information ats[2];
2715
2716   ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
2717   ats[0].value = htonl (1);
2718   ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
2719   ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
2720
2721 #if DEBUG_wlan
2722   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2723                    "Calling plugin->env->receive for session %p; %s; size: %u\n",
2724                    session, wlan_plugin_address_to_string (NULL,
2725                                                            session->mac->
2726                                                            addr.mac, 6),
2727                    htons (hdr->size));
2728 #endif
2729
2730   plugin->env->receive (plugin->env->cls, &(session->target), hdr,
2731                         (const struct GNUNET_ATS_Information *) &ats, 2,
2732                         session, (const char *) &session->mac->addr,
2733                         sizeof (session->mac->addr));
2734 }
2735
2736 /**
2737  * Function used for to process the data received from the wlan interface
2738  *
2739  * @param cls the plugin handle
2740  * @param session_light pointer to the struct holding known informations
2741  * @param hdr hdr of the GNUNET_MessageHeader
2742  * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS for info
2743  */
2744 static void
2745 wlan_data_helper (void *cls, struct Session_light *session_light,
2746                   const struct GNUNET_MessageHeader *hdr,
2747                   const struct Radiotap_rx *rxinfo)
2748 {
2749   struct Plugin *plugin = cls;
2750   struct FragmentMessage *fm;
2751   struct FragmentMessage *fm2;
2752   struct GNUNET_PeerIdentity tmpsource;
2753
2754   GNUNET_assert (plugin != NULL);
2755
2756   //ADVERTISEMENT
2757   if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2758   {
2759
2760     //TODO better DOS protection, error handling
2761     //TODO test first than create session
2762     GNUNET_assert (session_light != NULL);
2763
2764 #if DEBUG_wlan
2765     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2766                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_HELLO size: %u; %s\n",
2767                      ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2768                                                                        session_light->addr.
2769                                                                        mac, 6));
2770 #endif
2771
2772     if (session_light->macendpoint == NULL)
2773     {
2774       session_light->macendpoint =
2775           get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2776     }
2777
2778
2779     if (GNUNET_HELLO_get_id
2780         ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
2781     {
2782       session_light->session =
2783           search_session (plugin, session_light->macendpoint, &tmpsource);
2784       if (session_light->session == NULL)
2785       {
2786         session_light->session =
2787             create_session (plugin, session_light->macendpoint, &tmpsource);
2788       }
2789       GNUNET_STATISTICS_update (plugin->env->stats,
2790                                 _("# wlan hello messages received"), 1,
2791                                 GNUNET_NO);
2792       plugin->env->receive (plugin->env->cls, &session_light->session->target,
2793                             hdr, NULL, 0, session_light->session,
2794                             (const char *) &session_light->session->mac->addr,
2795                             sizeof (session_light->session->mac->addr));
2796     }
2797     else
2798     {
2799       GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2800                        "WLAN client not in session list and hello message is not okay\n");
2801       return;
2802     }
2803   }
2804
2805   //FRAGMENT
2806
2807   else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT)
2808   {
2809
2810     GNUNET_assert (session_light != NULL);
2811     if (session_light->macendpoint == NULL)
2812     {
2813       session_light->macendpoint =
2814           get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2815     }
2816
2817 #if DEBUG_wlan
2818     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2819                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT with size: %u; mac endpoint %p: %s\n",
2820                      ntohs (hdr->size), session_light->macendpoint,
2821                      wlan_plugin_address_to_string (NULL,
2822                                                     session_light->addr.mac,
2823                                                     6));
2824 #endif
2825
2826     GNUNET_STATISTICS_update (plugin->env->stats,
2827                               _("# wlan fragments received"), 1, GNUNET_NO);
2828     int ret =
2829         GNUNET_DEFRAGMENT_process_fragment (session_light->macendpoint->defrag,
2830                                             hdr);
2831
2832     if (ret == GNUNET_NO)
2833     {
2834       session_light->macendpoint->dups++;
2835     }
2836     else if (ret == GNUNET_OK)
2837     {
2838       session_light->macendpoint->fragc++;
2839     }
2840     set_next_send (plugin);
2841
2842   }
2843
2844   //ACK
2845
2846   else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT_ACK)
2847   {
2848     GNUNET_assert (session_light != NULL);
2849     if (session_light->macendpoint == NULL)
2850     {
2851       session_light->macendpoint =
2852           get_macendpoint (plugin, &session_light->addr, GNUNET_NO);
2853     }
2854
2855     if (session_light->macendpoint == NULL)
2856     {
2857 #if DEBUG_wlan
2858       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2859                        "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n",
2860                        ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2861                                                                          session_light->addr.mac,
2862                                                                          6));
2863 #endif
2864       return;
2865     }
2866
2867 #if DEBUG_wlan
2868     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2869                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; mac endpoint: %p; %s\n",
2870                      ntohs (hdr->size), session_light->macendpoint,
2871                      wlan_plugin_address_to_string (NULL,
2872                                                     session_light->addr.mac,
2873                                                     6));
2874 #endif
2875     fm = session_light->macendpoint->sending_messages_head;
2876     while (fm != NULL)
2877     {
2878       fm2 = fm->next;
2879       GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"),
2880                                 1, GNUNET_NO);
2881       int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
2882
2883       if (ret == GNUNET_OK)
2884       {
2885 #if DEBUG_wlan_retransmission > 1
2886         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2887                          "Got last ack, finished fragment message %p\n", fm);
2888 #endif
2889         session_light->macendpoint->acks++;
2890         fm->session->last_activity = GNUNET_TIME_absolute_get ();
2891         session_light->macendpoint->last_activity = fm->session->last_activity;
2892         free_fragment_message (plugin, fm);
2893         check_fragment_queue (plugin);
2894         return;
2895       }
2896       if (ret == GNUNET_NO)
2897       {
2898 #if DEBUG_wlan_retransmission > 1
2899         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2900                          "Got ack for: %p\n", fm);
2901 #endif
2902         session_light->macendpoint->acks++;
2903         return;
2904       }
2905       if (ret == GNUNET_SYSERR)
2906       {
2907
2908       }
2909
2910       fm = fm2;
2911     }
2912
2913 #if DEBUG_wlan_retransmission > 1
2914     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2915                      "WLAN fragment not in fragment list\n");
2916 #endif
2917     return;
2918
2919   }
2920   else
2921   {
2922     // TODO Wrong data?
2923     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2924                      "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2925                      ntohs (hdr->type), ntohs (hdr->size));
2926     GNUNET_break (0);
2927     return;
2928   }
2929
2930 #if 0
2931   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2932                    "Helper finished\n");
2933 #endif
2934
2935 }
2936
2937 #if DEBUG_wlan
2938 /**
2939  * Function to print mac addresses nice *
2940  * @param pointer to 6 byte with the mac address
2941  * @return pointer to the chars which hold the print out
2942  */
2943 static const char *
2944 macprinter (const u_int8_t * mac)
2945 {
2946   static char macstr[20];
2947
2948   GNUNET_snprintf (macstr, sizeof (macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2949                    mac[2], mac[3], mac[4], mac[5]);
2950   return macstr;
2951 }
2952 #endif
2953
2954 /**
2955  * Function for the scheduler if a mac endpoint times out
2956  * @param cls pointer to the MacEndpoint
2957  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
2958  */
2959 static void
2960 macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2961 {
2962   struct MacEndpoint *endpoint = cls;
2963
2964   GNUNET_assert (endpoint != NULL);
2965   endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2966   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2967   {
2968     return;
2969   }
2970   if (GNUNET_TIME_absolute_get_remaining
2971       (GNUNET_TIME_absolute_add
2972        (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
2973   {
2974     GNUNET_assert (endpoint->plugin != NULL);
2975     GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
2976                               _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
2977     free_macendpoint (endpoint->plugin, endpoint);
2978   }
2979   else
2980   {
2981     endpoint->timeout_task =
2982         GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
2983                                       endpoint);
2984   }
2985 }
2986
2987 /**
2988  * function to create an macendpoint
2989  * @param plugin pointer to the plugin struct
2990  * @param addr pointer to the macaddress
2991  * @return returns a macendpoint
2992  */
2993 static struct MacEndpoint *
2994 create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr)
2995 {
2996   struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint));
2997
2998   GNUNET_assert (plugin != NULL);
2999   GNUNET_STATISTICS_update (plugin->env->stats,
3000                             _("# wlan mac endpoints created"), 1, GNUNET_NO);
3001   newend->addr = *addr;
3002   newend->plugin = plugin;
3003   newend->addr = *addr;
3004   newend->fragment_messages_out_count = 0;
3005   newend->defrag =
3006       GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
3007                                         MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
3008                                         newend, &wlan_data_message_handler,
3009                                         &add_ack_for_send);
3010   newend->last_activity = GNUNET_TIME_absolute_get ();
3011   newend->timeout_task =
3012       GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
3013                                     newend);
3014
3015   plugin->mac_count++;
3016   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
3017                          plugin->mac_count, GNUNET_NO);
3018   GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend);
3019 #if DEBUG_wlan
3020   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3021                    "New Mac Endpoint %p: %s\n", newend,
3022                    wlan_plugin_address_to_string (NULL, newend->addr.mac, 6));
3023 #endif
3024   return newend;
3025 }
3026
3027 /**
3028  * Function used for to process the data from the suid process
3029  *
3030  * @param cls the plugin handle
3031  * @param client client that send the data (not used)
3032  * @param hdr header of the GNUNET_MessageHeader
3033  */
3034 static void
3035 wlan_process_helper (void *cls, void *client,
3036                      const struct GNUNET_MessageHeader *hdr)
3037 {
3038   struct Plugin *plugin = cls;
3039   struct ieee80211_frame *wlanIeeeHeader = NULL;
3040   struct Session_light *session_light = NULL;
3041   struct Radiotap_rx *rxinfo;
3042   const struct GNUNET_MessageHeader *temp_hdr = NULL;
3043
3044   int datasize = 0;
3045   int pos;
3046
3047   GNUNET_assert (plugin != NULL);
3048   switch (ntohs (hdr->type))
3049   {
3050   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
3051 #if DEBUG_wlan
3052     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3053                      "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
3054                      ntohs (hdr->size));
3055 #endif
3056
3057     GNUNET_STATISTICS_update (plugin->env->stats,
3058                               _("# wlan WLAN_HELPER_DATA received"), 1,
3059                               GNUNET_NO);
3060     //call wlan_process_helper with the message inside, later with wlan: analyze signal
3061     if (ntohs (hdr->size) <
3062         sizeof (struct ieee80211_frame) +
3063         2 * sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
3064     {
3065 #if DEBUG_wlan
3066       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3067                        "Size of packet is too small; size: %u min size: %u\n",
3068                        ntohs (hdr->size),
3069                        sizeof (struct ieee80211_frame) +
3070                        sizeof (struct GNUNET_MessageHeader));
3071 #endif
3072       //GNUNET_break (0);
3073       /* FIXME: restart SUID process */
3074       return;
3075     }
3076
3077     rxinfo = (struct Radiotap_rx *) &hdr[1];
3078     wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
3079
3080     //process only if it is an broadcast or for this computer both with the gnunet bssid
3081
3082     //check for bssid
3083     if (memcmp
3084         (&(wlanIeeeHeader->i_addr3), &mac_bssid_gnunet,
3085          sizeof (struct MacAddress)) == 0)
3086     {
3087       //check for broadcast or mac
3088       if ((memcmp
3089            (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
3090             sizeof (struct MacAddress)) == 0) ||
3091           (memcmp
3092            (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
3093             sizeof (struct MacAddress)) == 0))
3094       {
3095         //if packet is from us return
3096         if ((memcmp
3097              (&(wlanIeeeHeader->i_addr2), &(plugin->mac_address),
3098               sizeof (struct MacAddress)) == 0))
3099         {
3100           return;
3101         }
3102         // process the inner data
3103
3104
3105         datasize =
3106             ntohs (hdr->size) - sizeof (struct ieee80211_frame) -
3107             sizeof (struct GNUNET_MessageHeader) - sizeof (struct Radiotap_rx);
3108
3109         session_light = GNUNET_malloc (sizeof (struct Session_light));
3110         memcpy (&session_light->addr, &(wlanIeeeHeader->i_addr2),
3111                 sizeof (struct MacAddress));
3112         //session_light->session = search_session(plugin,session_light->addr);
3113         GNUNET_STATISTICS_update (plugin->env->stats,
3114                                   _("# wlan messages for this client received"),
3115                                   1, GNUNET_NO);
3116
3117         pos = 0;
3118         while (pos < datasize)
3119         {
3120           temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1] + pos;
3121           if (ntohs (temp_hdr->size) <= datasize + pos)
3122           {
3123             GNUNET_STATISTICS_update (plugin->env->stats,
3124                                       _
3125                                       ("# wlan messages inside WLAN_HELPER_DATA received"),
3126                                       1, GNUNET_NO);
3127             wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
3128           }
3129           else
3130           {
3131 #if DEBUG_wlan
3132             GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3133                              "Size of packet is too small; size: %u > size of packet: %u\n",
3134                              ntohs (temp_hdr->size), datasize + pos);
3135 #endif
3136           }
3137           pos += ntohs (temp_hdr->size);
3138
3139         }
3140
3141         //clean up
3142         GNUNET_free (session_light);
3143       }
3144       else
3145       {
3146 #if DEBUG_wlan
3147         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3148                          "Func wlan_process_helper got wrong MAC: %s\n",
3149                          macprinter (wlanIeeeHeader->i_addr1));
3150 #endif
3151       }
3152     }
3153     else
3154     {
3155 #if DEBUG_wlan
3156       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3157                        "Func wlan_process_helper got wrong BSSID: %s\n",
3158                        macprinter (wlanIeeeHeader->i_addr2));
3159 #endif
3160     }
3161     break;
3162   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
3163     //TODO more control messages
3164     if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
3165     {
3166       GNUNET_break (0);
3167       /* FIXME: restart SUID process */
3168       return;
3169     }
3170     memcpy (&plugin->mac_address, &hdr[1], sizeof (struct MacAddress));
3171 #if DEBUG_wlan
3172     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3173                      "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
3174                      wlan_plugin_address_to_string (cls, &plugin->mac_address,
3175                                                     sizeof (struct
3176                                                             MacAddress)));
3177 #endif
3178     plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
3179                                  &plugin->mac_address,
3180                                  sizeof (struct MacAddress));
3181     break;
3182   default:
3183 #if DEBUG_wlan
3184     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3185                      "Func wlan_process_helper got unknown message with number %u, size %u\n",
3186                      ntohs (hdr->type), ntohs (hdr->size));
3187
3188 #endif
3189 #if DEBUG_wlan_msg_dump > 1
3190     hexdump (hdr, GNUNET_MIN (ntohs (hdr->size), 256));
3191 #endif
3192     GNUNET_break (0);
3193     return;
3194   }
3195 }
3196
3197 /**
3198  * Exit point from the plugin.
3199  * @param cls pointer to the api struct
3200  */
3201
3202 //FIXME cleanup
3203 void *
3204 libgnunet_plugin_transport_wlan_done (void *cls)
3205 {
3206   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3207   struct Plugin *plugin = api->cls;
3208   struct MacEndpoint *endpoint = plugin->mac_head;
3209   struct MacEndpoint *endpoint_next;
3210
3211 #if DEBUG_wlan
3212   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3213                    "libgnunet_plugin_transport_wlan_done started\n");
3214 #endif
3215
3216   wlan_transport_stop_wlan_helper (plugin);
3217
3218   GNUNET_assert (cls != NULL);
3219   //free sessions
3220   while (endpoint != NULL)
3221   {
3222     endpoint_next = endpoint->next;
3223     free_macendpoint (plugin, endpoint);
3224     endpoint = endpoint_next;
3225
3226   }
3227
3228
3229   if (plugin->suid_tokenizer != NULL)
3230     GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
3231
3232   if (plugin->data_tokenizer != NULL)
3233     GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
3234
3235   GNUNET_free_non_null (plugin->interface);
3236   GNUNET_free (plugin);
3237   GNUNET_free (api);
3238   return NULL;
3239 }
3240
3241 /**
3242  * Entry point for the plugin.
3243  *
3244  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3245  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3246  */
3247 void *
3248 libgnunet_plugin_transport_wlan_init (void *cls)
3249 {
3250   //struct GNUNET_SERVICE_Context *service;
3251   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3252   struct GNUNET_TRANSPORT_PluginFunctions *api;
3253   struct Plugin *plugin;
3254
3255   GNUNET_assert (cls != NULL);
3256
3257   plugin = GNUNET_malloc (sizeof (struct Plugin));
3258   plugin->env = env;
3259   plugin->pendingsessions = 0;
3260   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
3261                          plugin->pendingsessions, GNUNET_NO);
3262   plugin->mac_count = 0;
3263   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
3264                          plugin->mac_count, GNUNET_NO);
3265   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3266   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3267   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3268   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
3269                                  GNUNET_BANDWIDTH_value_init (100 * 1024 *
3270                                                               1024 / 8), 100);
3271
3272   plugin->suid_tokenizer =
3273       GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
3274
3275   plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
3276
3277   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3278   //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3279
3280   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3281   api->cls = plugin;
3282   api->send = &wlan_plugin_send;
3283   api->get_session = &wlan_plugin_get_session;
3284   api->disconnect = &wlan_plugin_disconnect;
3285   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3286   api->check_address = &wlan_plugin_address_suggested;
3287   api->address_to_string = &wlan_plugin_address_to_string;
3288
3289   //read config
3290
3291   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
3292   {
3293     if (GNUNET_SYSERR ==
3294         GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
3295                                                "TESTMODE", &(plugin->testmode)))
3296       plugin->testmode = 0;     //default value
3297   }
3298
3299   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
3300   {
3301     if (GNUNET_CONFIGURATION_get_value_string
3302         (env->cfg, "transport-wlan", "INTERFACE",
3303          &(plugin->interface)) != GNUNET_YES)
3304     {
3305       libgnunet_plugin_transport_wlan_done (api);
3306       return NULL;
3307     }
3308   }
3309
3310   //start the plugin
3311   wlan_transport_start_wlan_helper (plugin);
3312   set_next_beacon_time (plugin);
3313   set_next_send (plugin);
3314 #if DEBUG_wlan
3315   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3316                    "wlan init finished\n");
3317 #endif
3318
3319   return api;
3320 }
3321
3322 /* end of plugin_transport_wlan.c */