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