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