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