wlan receive implemented
[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 DEBUG_wlan GNUNET_NO
53
54 /**
55  * After how long do we expire an address that we
56  * learned from another peer if it is not reconfirmed
57  * by anyone?
58  */
59 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
60
61 /**
62  * Initial handshake message for a session.
63  */
64 struct WelcomeMessage
65 {
66   /**
67    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
68    */
69   struct GNUNET_MessageHeader header;
70
71   /**
72    * Identity of the node connecting (TCP client)
73    */
74   struct GNUNET_PeerIdentity clientIdentity;
75
76 };
77
78 /**
79  * Encapsulation of all of the state of the plugin.
80  */
81 struct Plugin
82 {
83   /**
84    * Our environment.
85    */
86   struct GNUNET_TRANSPORT_PluginEnvironment *env;
87
88   /**
89    * List of open sessions. head
90    */
91   struct Sessionqueue *sessions;
92
93   /**
94    * List of open sessions. tail
95    */
96   struct Sessionqueue *sessions_tail;
97
98   /**
99    * Number of sessions
100    */
101
102   int session_count;
103
104   /**
105    * encapsulation to the local wlan server prog
106    */
107
108   struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
109
110
111   /**
112    * stdout pipe handle for the gnunet-wlan-helper process
113    */
114   struct GNUNET_DISK_PipeHandle *server_stdout;
115
116   /**
117    * stdout file handle for the gnunet-wlan-helper process
118    */
119   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
120
121   /**
122    * stdin pipe handle for the gnunet-wlan-helper process
123    */
124   struct GNUNET_DISK_PipeHandle *server_stdin;
125
126   /**
127    * stdin file handle for the gnunet-wlan-helper process
128    */
129   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
130
131   /**
132    * ID of the gnunet-wlan-server std read task
133    */
134   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
135
136   /**
137    * ID of the gnunet-wlan-server std read task
138    */
139   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
140
141   /**
142    * ID of the delay task for writing
143    */
144   GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
145
146   /**
147    * The process id of the wlan process
148    */
149   struct GNUNET_OS_Process *server_proc;
150
151   /**
152    * The interface of the wlan card given to us by the user.
153    */
154   char *interface;
155
156   /**
157    * The mac_address of the wlan card given to us by the helper.
158    */
159   char *mac_address;
160
161   /**
162    * Sessions currently pending for transmission
163    * to this peer, if any.
164    */
165   struct Sessionqueue * pending_Sessions;
166
167   /**
168     * Sessions currently pending for transmission
169     * to this peer (tail), if any.
170     */
171   struct Sessionqueue * pending_Sessions_tail;
172
173   /**
174    * number of pending sessions
175    */
176   unsigned int pendingsessions;
177
178   /**
179    * Messages in the fragmentation queue, head
180    */
181
182   struct FragmentMessage * pending_Fragment_Messages_head;
183
184   /**
185    * Messages in the fragmentation queue, tail
186    */
187
188   struct FragmentMessage * pending_Fragment_Messages_tail;
189
190   /**
191      * number of pending fragment message
192      */
193
194   unsigned int pending_fragment_messages;
195
196   /**
197    * time of the next "hello-beacon"
198    */
199
200   struct GNUNET_TIME_Absolute beacon_time;
201
202 };
203
204 /**
205  * Queue of sessions, for the general session queue and the pending session queue
206  */
207
208 struct Sessionqueue
209 {
210         struct Sessionqueue * next;
211         struct Sessionqueue * prev;
212         struct Session * content;
213 };
214
215 /**
216  * Queue of ack received for messages send
217  */
218
219 struct AckQueue
220 {
221         struct AckQueue * next;
222         struct AckQueue * prev;
223         int fragment_num; //TODO change it to offset
224 };
225
226 /**
227  * Queue for the fragments received
228  */
229
230 struct RecQueue
231 {
232         struct RecQueue * next;
233         struct RecQueue * prev;
234         uint16_t num;
235         char * msg;
236         uint16_t size;
237 };
238
239 /**
240  * Information kept for each message that is yet to
241  * be transmitted.
242  */
243 struct PendingMessage
244 {
245
246   /**
247    * The pending message
248    */
249   char *msg;
250
251   /**
252    * Continuation function to call once the message
253    * has been sent.  Can be NULL if there is no
254    * continuation to call.
255    */
256   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
257
258   /**
259    * Cls for transmit_cont
260    */
261   void * transmit_cont_cls;
262
263   /**
264    * Timeout value for the pending message.
265    */
266   struct GNUNET_TIME_Absolute timeout;
267
268   /**
269    * Size of the message
270    */
271   size_t message_size;
272
273 };
274
275 /**
276  * Session infos gathered from a messages
277  */
278
279 struct Session_light
280 {
281   /**
282    * the session this message belongs to
283    */
284   struct Session * session;
285   /**
286    * peer mac address
287    */
288   uint8_t addr[6];
289 };
290
291 /**
292  * Session handle for connections.
293  */
294 struct Session
295 {
296
297   /**
298    * API requirement.
299    */
300   struct SessionHeader header;
301
302   /**
303    * Pointer to the global plugin struct.
304    */
305   struct Plugin *plugin;
306
307   /**
308    * Message currently pending for transmission
309    * to this peer, if any.
310    */
311   struct PendingMessage *pending_message;
312
313   /**
314    * To whom are we talking to (set to our identity
315    * if we are still waiting for the welcome message)
316    */
317   struct GNUNET_PeerIdentity target;
318
319   /**
320    * encapsulation of the receive data
321    */
322   //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
323
324   /**
325    * offset of the next fragment for the receive_token, -1 means last message finished
326    */
327
328   //int rec_offset;
329
330   /**
331    * size of the message received, -1 means that the size is not known, -2 means no message received
332    */
333
334   int rec_size;
335
336   /**
337    * Sorted queue with the fragments received; head
338    */
339
340   struct RecQueue * frag_head;
341
342   /**
343    * Sorted queue with the fragments received; tail
344    */
345
346   struct RecQueue * frag_tail;
347
348   /**
349    * peer mac address
350    */
351   char addr[6];
352
353   /**
354    * Address of the other peer (either based on our 'connect'
355    * call or on our 'accept' call).
356    */
357   void *connect_addr;
358
359   /**
360    * Last activity on this connection.  Used to select preferred
361    * connection.
362    */
363   struct GNUNET_TIME_Absolute last_activity;
364
365   /**
366    * current number for message incoming, to distinguish between the messages
367    */
368   uint32_t message_id_in;
369
370   /**
371    * current number for message outgoing, to distinguish between the messages
372    */
373   uint32_t message_id_out;
374
375   /**
376    * does this session have a message in the fragment queue
377    */
378
379   int has_fragment;
380
381 };
382
383
384
385
386 struct FragmentMessage
387 {
388         /**
389          * Session this message belongs to
390          */
391
392         struct Session *session;
393
394         /**
395         * This is a doubly-linked list.
396         */
397         struct FragmentMessage *next;
398
399         /**
400         * This is a doubly-linked list.
401         */
402         struct FragmentMessage *prev;
403
404         /**
405         * The pending message
406         */
407         char *msg;
408
409         /**
410         * Timeout value for the pending message.
411         */
412         struct GNUNET_TIME_Absolute timeout;
413
414         /**
415         * Timeout value for the pending fragments.
416         * Stores the time when the next msg fragment ack has to be received
417         */
418         struct GNUNET_TIME_Absolute next_ack;
419
420         /**
421         * Sorted queue with the acks received for fragments; head
422         */
423
424         struct AckQueue * head;
425
426         /**
427         * Sorted queue with the acks received for fragments; tail
428         */
429
430         struct AckQueue * tail;
431
432         /**
433         * Size of the message
434         */
435         size_t message_size;
436
437         /**
438         * pos / next fragment number in the message, for fragmentation/segmentation,
439         * some acks can be missing but there is still time
440         */
441         uint32_t message_pos;
442
443 };
444
445 /**
446  * Header for messages which need fragmentation
447  */
448 struct WlanHeader
449 {
450
451   struct GNUNET_MessageHeader header;
452
453   /**
454    * checksum/error correction
455    */
456   uint32_t crc GNUNET_PACKED;
457
458   /**
459    * To whom are we talking to (set to our identity
460    * if we are still waiting for the welcome message)
461    */
462   struct GNUNET_PeerIdentity target;
463
464   // followed by payload
465
466 };
467
468 /**
469  * Header for messages which need fragmentation
470  */
471 struct FragmentationHeader
472 {
473
474   struct GNUNET_MessageHeader header;
475
476   /**
477    * To whom are we talking to (set to our identity
478    * if we are still waiting for the welcome message)
479    */
480   // struct GNUNET_PeerIdentity target GNUNET_PACKED;
481
482   /**
483    * ID of message, to distinguish between the messages, picked randomly.
484    */
485   uint32_t message_id GNUNET_PACKED;
486
487   /**
488    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
489    */
490   uint16_t fragment_off_or_num GNUNET_PACKED;
491
492   /**
493    * CRC of fragment (for error checking)
494    */
495   uint16_t message_crc GNUNET_PACKED;
496
497   /**
498    * Flags
499    * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
500    * // 0x2 has data (not only ack)
501    * // 0x4 last fragment of message
502    * // 0x8 new message
503    */
504   //  uint32_t flags GNUNET_PACKED;
505
506   /**
507    * checksum/error correction
508    */
509   // uint32_t crc GNUNET_PACKED;
510
511   // followed by payload unless ACK
512
513 };
514
515 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
516
517 int
518 getRadiotapHeader(struct RadiotapHeader * Header);
519
520 int
521 getWlanHeader(struct IeeeHeader * Header);
522
523 static int
524 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
525
526 uint16_t
527 getcrc16(const char *msgbuf, size_t msgbuf_size);
528
529 static void
530 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
531
532 static void
533 check_fragment_queue(struct Plugin * plugin);
534
535 uint32_t
536 getcrc32(const char *msgbuf, size_t msgbuf_size);
537
538 /**
539  * get the next message number, at the moment just a random one
540  *
541  */
542 //TODO doxigen
543 uint32_t
544 get_next_message_id()
545 {
546   return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
547 }
548
549 /**
550  * start next message number generator
551  */
552 //TODO doxigen
553 void
554 start_next_message_id()
555 {
556   //GNUNET_CRYPTO_random_init;
557 }
558
559 /**
560  * search for a session with the addr
561  *
562  * @param plugin pointer to the plugin struct
563  * @param addr pointer to the mac address of the peer
564  * @return returns the session
565  */
566
567 static struct Session *
568 search_session(struct Plugin *plugin, const uint8_t * addr)
569 {
570   struct Sessionqueue * queue = plugin->sessions;
571   struct Sessionqueue * lastitem = NULL;
572
573   //just look at all the session for the needed one
574   while (queue != NULL)
575     {
576       // content is never NULL
577       GNUNET_assert (queue->content == NULL);
578       char * addr2 = queue->content->addr;
579       if (memcmp(addr, addr2, 6) == 0)
580         {
581           //sesion found
582           return queue->content;
583         }
584       // try next
585       lastitem = queue;
586       queue = queue->next;
587     }
588   return NULL;
589 }
590
591 /**
592  * create a new session
593  *
594  * @param plugin pointer to the plugin struct
595  * @param addr pointer to the mac address of the peer
596  * @return returns the session
597  */
598
599 static struct Session *
600 create_session(struct Plugin *plugin,const uint8_t * addr)
601 {
602   struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
603
604   GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
605
606   queue->content = GNUNET_malloc (sizeof (struct Session));
607   queue->content->plugin = plugin;
608   memcpy(queue->content->addr, addr, 6);
609   queue->content->message_id_out = get_next_message_id();
610   queue->content->has_fragment = 0;
611   queue->content->rec_size = -2;
612
613   plugin->session_count++;
614   return queue->content;
615 }
616
617 /**
618  * get Session from address, create if no session exists
619  *
620  * @param plugin pointer to the plugin struct
621  * @param addr pointer to the mac address of the peer
622  * @return returns the session
623  */
624 //TODO add other possibilities to find the right session (are there other?)
625 static struct Session *
626 get_Session(struct Plugin *plugin, const uint8_t * addr)
627 {
628   struct Session * session = search_session(plugin, addr);
629   if (session != NULL)
630     {
631       return session;
632     }
633   // new session
634   return create_session(plugin, addr);
635
636   /* -- not needed, layer above already has it--
637    //queue welcome message for new sessions, not realy needed
638    //struct WelcomeMessage welcome;
639    struct PendingMessage *pm;
640    pm = GNUNET_malloc (sizeof (struct PendingMessage));
641    pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
642    pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
643    //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
644    //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
645    //welcome.clientIdentity = *plugin->env->my_identity;
646    memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
647    pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
648    queue->content->pending_message = pm;
649    plugin->pendingsessions ++;
650    GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
651
652    check_fragment_queue(plugin);
653    */
654 }
655
656 /**
657  * Queue the session to send data
658  */
659 //TODO doxigen
660 static void
661 queue_Session (struct Plugin *plugin,
662                 struct Session * session)
663 {
664         struct Sessionqueue * queue = plugin->pending_Sessions;
665         struct Sessionqueue * lastitem = NULL;
666
667         while (queue != NULL){
668                 // content is never NULL
669                 GNUNET_assert (queue->content == NULL);
670                 // is session already in queue?
671                 if (session == queue->content){
672                         return;
673                 }
674                 // try next
675                 lastitem = queue;
676                 queue = queue->next;
677         }
678
679         // Session is not in the queue
680
681         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
682         queue->content = session;
683
684         //insert at the tail
685         GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
686                         plugin->pending_Sessions_tail,
687                         plugin->pending_Sessions_tail, queue);
688         plugin->pendingsessions ++;
689
690 }
691
692 //TODO doxigen
693 static void
694 free_acks (struct FragmentMessage * fm){
695         struct AckQueue * fq;
696         while (fm->head != NULL){
697                 fq = fm->head;
698                 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
699                 GNUNET_free(fq);
700         }
701 }
702
703 //TODO doxigen
704 /**
705  * Function to schedule the write task, executed after a delay
706  */
707 static void
708 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
709 {
710   struct Plugin * plugin = cls;
711   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
712
713   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
714     return;
715
716   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
717   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
718     {
719       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
720           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
721           &do_transmit, plugin);
722     }
723 }
724
725 //TODO doxigen
726 /**
727  * Function to calculate the time of the next periodic "hello-beacon"
728  */
729 static void
730 set_next_beacon_time(struct Plugin * const plugin)
731 {
732   //under 10 known peers: once a second
733   if (plugin->session_count < 10)
734     {
735       plugin->beacon_time = GNUNET_TIME_absolute_add(
736           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
737     }
738   //under 30 known peers: every 10 seconds
739   else if (plugin->session_count < 30)
740     {
741       plugin->beacon_time = GNUNET_TIME_absolute_add(
742           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
743               GNUNET_TIME_UNIT_SECONDS, 10));
744     }
745   //over 30 known peers: once a minute
746   else
747     {
748       plugin->beacon_time = GNUNET_TIME_absolute_add(
749           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
750     }
751 }
752
753
754 //TODO doxigen
755 struct GNUNET_TIME_Relative
756 get_next_frag_timeout(struct FragmentMessage * fm)
757 {
758   return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
759       fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
760 }
761
762 //TODO doxigen
763 /**
764  * Function to get the timeout value for acks for this session
765  */
766
767 struct GNUNET_TIME_Relative
768 get_ack_timeout (struct FragmentMessage * fm){
769         return FRAGMENT_TIMEOUT;
770 }
771
772 //TODO doxigen
773 /**
774  * Function to set the timer for the next timeout of the fragment queue
775  */
776 static void
777 check_next_fragment_timeout(struct Plugin * const plugin)
778 {
779   struct FragmentMessage * fm;
780   struct GNUNET_TIME_Relative next_send;
781
782   next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
783
784   //cancel old task
785   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
786     {
787       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
788     }
789   fm = plugin->pending_Fragment_Messages_head;
790
791   GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
792
793   //check if there are some fragments in the queue
794   if (fm != NULL)
795     {
796       next_send
797           = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
798     }
799   plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
800       &delay_fragment_task, plugin);
801 }
802
803
804
805 //TODO doxigen
806 /**
807  * Function to get the next queued Session, removes the session from the queue
808  */
809
810 static struct Session *
811 get_next_queue_Session (struct Plugin * plugin){
812         struct Session * session;
813         struct Sessionqueue * sessionqueue;
814         struct Sessionqueue * sessionqueue_alt;
815         struct PendingMessage * pm;
816         sessionqueue = plugin->pending_Sessions;
817         while (sessionqueue != NULL){
818                 session = sessionqueue->content;
819                 pm = session->pending_message;
820
821                 //check for message timeout
822                 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
823                         //check if session has no message in the fragment queue
824                         if (! session->has_fragment){
825                                 plugin->pendingsessions --;
826                                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
827                                                 plugin->pending_Sessions_tail, sessionqueue);
828                                 GNUNET_free(sessionqueue);
829
830                                 return session;
831                         } else {
832                                 sessionqueue = sessionqueue->next;
833                         }
834                 } else {
835
836                         session->pending_message = NULL;
837                         //call the cont func that it did not work
838                         if (pm->transmit_cont != NULL)
839                           pm->transmit_cont (pm->transmit_cont_cls,
840                                                 &(session->target), GNUNET_SYSERR);
841                         GNUNET_free(pm->msg);
842                         GNUNET_free(pm);
843
844                         sessionqueue_alt = sessionqueue;
845                         sessionqueue = sessionqueue->next;
846                         plugin->pendingsessions --;
847                         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
848                                         plugin->pending_Sessions_tail, sessionqueue_alt);
849
850                         GNUNET_free(sessionqueue_alt);
851
852                 }
853
854
855         }
856         return NULL;
857 }
858
859 //TODO doxigen
860 /**
861  * Function to sort the message into the message fragment queue
862  */
863 static void
864 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
865         struct FragmentMessage * fm2;
866         //sort into the list at the right position
867
868         fm2 = plugin->pending_Fragment_Messages_head;
869
870         while (fm2 != NULL){
871                 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
872                         break;
873                 } else {
874                         fm2 = fm2->next;
875                 }
876         }
877
878         GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
879                         plugin->pending_Fragment_Messages_tail,fm2,fm);
880 }
881
882 //TODO doxigen
883 static void
884 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
885 {
886   if (fm != NULL)
887     {
888       free_acks(fm);
889       GNUNET_free_non_null(fm->msg);
890       GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
891           plugin->pending_Fragment_Messages_tail, fm);
892       GNUNET_free(fm);
893       plugin->pending_fragment_messages --;
894       check_fragment_queue(plugin);
895     }
896 }
897
898 //TODO doxigen
899 /**
900  * Function to check if there is some space in the fragment queue
901  */
902
903 static void
904 check_fragment_queue (struct Plugin * plugin){
905         struct Session * session;
906         struct FragmentMessage * fm;
907
908         struct PendingMessage * pm;
909
910         if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
911                 session = get_next_queue_Session(plugin);
912                 if (session != NULL){
913                         pm = session->pending_message;
914                         session->pending_message = NULL;
915                         session->has_fragment = 1;
916                         GNUNET_assert(pm != NULL);
917
918                         fm = GNUNET_malloc(sizeof(struct FragmentMessage));
919                         fm->message_size = pm->message_size;
920                         fm->msg = pm->msg;
921                         fm->session = session;
922                         fm->timeout.abs_value = pm->timeout.abs_value;
923                         fm->message_pos = 0;
924                         fm->next_ack = GNUNET_TIME_absolute_get();
925
926                         if (pm->transmit_cont != NULL)
927                                   pm->transmit_cont (pm->transmit_cont_cls,
928                                                         &(session->target), GNUNET_OK);
929                         GNUNET_free(pm);
930
931                         sort_fragment_into_queue(plugin,fm);
932                         plugin->pending_fragment_messages ++;
933
934                         //generate new message id
935                         session->message_id_out = get_next_message_id();
936
937                         //check if timeout changed
938                         check_next_fragment_timeout(plugin);
939                 }
940         }
941 }
942
943 static void
944 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
945   struct AckQueue * ack;
946   int counter = 0;
947
948   if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
949       * fm->tail->fragment_num)
950     {
951       ack = fm->head;
952       counter = 0;
953       //check if all acks are present
954       while (ack != NULL)
955         {
956           if (counter == ack->fragment_num)
957             {
958               counter ++;
959               ack = ack->next;
960             } else {
961               //ack is missing
962               return;
963             }
964         }
965       fm->session->has_fragment = 0;
966       free_fragment_message(plugin, fm);
967
968
969     }
970 }
971
972 /**
973  * Function called to when wlan helper is ready to get some data
974  *
975  * @param cls closure
976  * @param GNUNET_SCHEDULER_TaskContext
977  */
978
979 static void
980 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
981 {
982
983   struct Plugin * plugin = cls;
984   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
985
986   ssize_t bytes;
987
988   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
989     return;
990
991   struct Session * session = NULL;
992   struct FragmentMessage * fm = NULL;
993   struct IeeeHeader * ieeewlanheader = NULL;
994   struct RadiotapHeader * radioHeader = NULL;
995   struct GNUNET_MessageHeader * msgheader = NULL;
996   struct GNUNET_MessageHeader * msgheader2 = NULL;
997   struct FragmentationHeader fragheader;
998   uint16_t size = 0;
999   const char * copystart = NULL;
1000   uint16_t copysize = 0;
1001   uint copyoffset = 0;
1002   struct AckQueue * akt = NULL;
1003
1004   //test if a "hello-beacon" has to be send
1005   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1006     {
1007       //check if the message is not to big
1008       GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1009               *(plugin->env->our_hello)) <= WLAN_MTU);
1010       size = sizeof(struct GNUNET_MessageHeader)
1011           + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1012           + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1013           *(plugin->env->our_hello));
1014
1015       msgheader = GNUNET_malloc(size);
1016       msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
1017       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1018
1019       radioHeader = (struct RadiotapHeader *) &msgheader[1];
1020       getRadiotapHeader(radioHeader);
1021
1022       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1023       getWlanHeader(ieeewlanheader);
1024
1025       msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1026       msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello)));
1027       msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1028
1029       memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1030           *(plugin->env->our_hello)));
1031
1032
1033       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1034           size);
1035       GNUNET_assert(bytes == size);
1036
1037       set_next_beacon_time(plugin);
1038       check_next_fragment_timeout(plugin);
1039       return;
1040
1041     }
1042
1043
1044   fm = plugin->pending_Fragment_Messages_head;
1045   GNUNET_assert(fm != NULL);
1046   session = fm->session;
1047   GNUNET_assert(session != NULL);
1048
1049   // test if message timed out
1050   if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
1051           free_acks(fm);
1052           GNUNET_assert(plugin->pending_fragment_messages > 0);
1053           plugin->pending_fragment_messages --;
1054           GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1055                           plugin->pending_Fragment_Messages_tail, fm);
1056
1057           GNUNET_free(fm->msg);
1058
1059           GNUNET_free(fm);
1060           check_fragment_queue(plugin);
1061   } else {
1062
1063           if (fm->message_size > WLAN_MTU) {
1064                 size += sizeof(struct FragmentationHeader);
1065                 // check/set for retransmission
1066                 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
1067
1068                         // be positive and try again later :-D
1069                         fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1070                         // find first missing fragment
1071                         akt = fm->head;
1072                         fm->message_pos = 0;
1073
1074                         //test if ack 0 was already received
1075                         while (akt != NULL){
1076                                 //if fragment is present, take next
1077                                 if (akt->fragment_num == fm->message_pos) {
1078                                         fm->message_pos ++;
1079                                 }
1080                                 //next ack is bigger then the fragment number
1081                                 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1082                                 //and we send 3 again, the next number should be 4
1083                                 else if (akt->fragment_num > fm->message_pos) {
1084                                         break;
1085                                 }
1086
1087                                 akt = akt->next;
1088
1089                         }
1090
1091
1092                 }
1093
1094                 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
1095                 fragheader.fragment_off_or_num = htons(fm->message_pos);
1096                 fragheader.message_id = htonl(session->message_id_out);
1097
1098                 // start should be smaller then the packet size
1099                 GNUNET_assert(copyoffset < fm->message_size);
1100                 copystart = fm->msg + copyoffset;
1101
1102                 //size of the fragment is either the MTU - overhead
1103                 //or the missing part of the message in case this is the last fragment
1104                 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1105                                 WLAN_MTU - sizeof(struct FragmentationHeader));
1106                 fragheader.header.size = htons(copysize);
1107                 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1108
1109
1110                 //get the next missing fragment
1111                 akt = fm->head;
1112                 fm->message_pos ++;
1113
1114                 //test if ack was already received
1115                 while (akt != NULL){
1116                         //if fragment is present, take next
1117                         if (akt->fragment_num == fm->message_pos) {
1118                                 fm->message_pos ++;
1119                         }
1120                         //next ack is bigger then the fragment number
1121                         //in case there is something like this: (acks) 1, 2, 5, 6, ...
1122                         //and we send 3 again, the next number should be 4
1123                         else if (akt->fragment_num > fm->message_pos) {
1124                                 break;
1125                         }
1126
1127                         akt = akt->next;
1128                 }
1129           } else {
1130                 // there is no need to split
1131                 copystart = fm->msg;
1132                 copysize = fm->message_size;
1133           }
1134
1135         size += copysize;
1136         size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1137                 + sizeof(struct GNUNET_MessageHeader);
1138         msgheader = GNUNET_malloc(size);
1139         msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
1140         msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1141
1142         radioHeader = (struct RadiotapHeader*) &msgheader[1];
1143         getRadiotapHeader(radioHeader);
1144
1145         ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1146         getWlanHeader(ieeewlanheader);
1147
1148
1149         //could be faster if content is just send and not copyed before
1150         //fragmentheader is needed
1151         if (fm->message_size > WLAN_MTU){
1152                 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1153                 memcpy(&ieeewlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
1154                 memcpy(&ieeewlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
1155         } else {
1156                 memcpy(&ieeewlanheader[1],copystart,copysize);
1157         }
1158
1159         bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1160         GNUNET_assert(bytes == size);
1161
1162         //check if this was the last fragment of this message, if true then queue at the end of the list
1163         if (copysize + copyoffset >= fm->message_size){
1164                 GNUNET_assert(copysize + copyoffset == fm->message_size);
1165
1166                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1167                                 plugin->pending_Fragment_Messages_tail, fm);
1168
1169                 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1170                                 plugin->pending_Fragment_Messages_tail, fm);
1171                 // if fragments have opimized timeouts
1172                 //sort_fragment_into_queue(plugin,fm);
1173
1174         }
1175         check_next_fragment_timeout(plugin);
1176
1177   }
1178 }
1179
1180
1181 /**
1182  * 32bit CRC
1183  *
1184  * @param msgbuf pointer tor the data
1185  * @param msgbuf_size size of the data
1186  *
1187  * @return 32bit crc value
1188  */
1189
1190 uint32_t
1191 getcrc32 (const char *msgbuf,
1192                   size_t msgbuf_size){
1193         //TODO calc some crc
1194         return 0;
1195 }
1196
1197 /**
1198  * 16bit CRC
1199  *
1200  * @param msgbuf pointer tor the data
1201  * @param msgbuf_size size of the data
1202  *
1203  * @return 16bit crc value
1204  */
1205
1206 uint16_t
1207 getcrc16 (const char *msgbuf,
1208                   size_t msgbuf_size){
1209         //TODO calc some crc
1210         return 0;
1211 }
1212
1213 /**
1214  * Function that can be used by the transport service to transmit
1215  * a message using the plugin.
1216  *
1217  * @param cls closure
1218  * @param target who should receive this message
1219  * @param priority how important is the message
1220  * @param msgbuf the message to transmit
1221  * @param msgbuf_size number of bytes in 'msgbuf'
1222  * @param timeout when should we time out 
1223  * @param session which session must be used (or NULL for "any")
1224  * @param addr the address to use (can be NULL if the plugin
1225  *                is "on its own" (i.e. re-use existing TCP connection))
1226  * @param addrlen length of the address in bytes
1227  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1228  *                otherwise the plugin may use other addresses or
1229  *                existing connections (if available)
1230  * @param cont continuation to call once the message has
1231  *        been transmitted (or if the transport is ready
1232  *        for the next transmission call; or if the
1233  *        peer disconnected...)
1234  * @param cont_cls closure for cont
1235  * @return number of bytes used (on the physical network, with overheads);
1236  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1237  *         and does NOT mean that the message was not transmitted (DV)
1238  */
1239 static ssize_t
1240 wlan_plugin_send (void *cls,
1241                   const struct GNUNET_PeerIdentity * target,
1242                   const char *msgbuf,
1243                   size_t msgbuf_size,
1244                   unsigned int priority,
1245                   struct GNUNET_TIME_Relative timeout,
1246                   struct Session *session,
1247                   const void *addr,
1248                   size_t addrlen,
1249                   int force_address,
1250                   GNUNET_TRANSPORT_TransmitContinuation cont,
1251                   void *cont_cls)
1252 {
1253   struct Plugin * plugin = cls;
1254   struct PendingMessage * newmsg = NULL;
1255   struct WlanHeader * wlanheader = NULL;
1256   //check if msglen > 0
1257   GNUNET_assert(msgbuf_size > 0);
1258
1259   //get session if needed
1260   if (session == NULL)
1261     {
1262       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1263         {
1264           session = get_Session(plugin, addr);
1265         }
1266       else
1267         {
1268           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1269               _("Wlan Address len %d is wrong\n"), addrlen);
1270           return -1;
1271         }
1272     }
1273
1274   //TODO target "problem" not solved
1275   session->target = *target;
1276
1277   //queue message:
1278   //first queue session
1279   queue_Session(plugin, session);
1280
1281   //queue message in session
1282   //test if there is no other message in the "queue"
1283   GNUNET_assert (session->pending_message == NULL);
1284
1285   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1286   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1287   wlanheader = (struct WlanHeader *) newmsg->msg;
1288   //copy msg to buffer, not fragmented / segmented yet, but with message header
1289   wlanheader->header.size = htons(msgbuf_size);
1290   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1291   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1292   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1293   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1294   newmsg->transmit_cont = cont;
1295   newmsg->transmit_cont_cls = cont_cls;
1296   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1297   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1298
1299   check_fragment_queue(plugin);
1300   //FIXME not the correct size
1301   return msgbuf_size;
1302
1303 }
1304
1305 static struct FragmentMessage *
1306 get_fragment_message_from_session(struct Session * session)
1307 {
1308   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1309   while (fm != NULL)
1310     {
1311       if (fm->session == session)
1312         {
1313           return fm;
1314         }
1315       fm = fm->next;
1316     }
1317   return NULL;
1318 }
1319
1320 /**
1321  * Function that can be used to force the plugin to disconnect
1322  * from the given peer and cancel all previous transmissions
1323  * (and their continuation).
1324  *
1325  * @param cls closure
1326  * @param target peer from which to disconnect
1327  */
1328 static void
1329 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1330 {
1331   struct Plugin *plugin = cls;
1332   struct Sessionqueue * queue = plugin->sessions;
1333   struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1334   struct PendingMessage * pm = NULL;
1335   struct FragmentMessage * fm;
1336
1337   // just look at all the session for the needed one
1338   while (queue != NULL)
1339     {
1340       // content is never NULL
1341       GNUNET_assert (queue->content == NULL);
1342       if (memcmp(target, &(queue->content->target),
1343           sizeof(struct GNUNET_PeerIdentity)) == 0)
1344         {
1345           //session found
1346           //is this session pending for send
1347           while (pendingsession != NULL)
1348             {
1349               if (pendingsession->content == queue->content)
1350                 {
1351                   plugin->pendingsessions --;
1352                   GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1353                       plugin->pending_Sessions_tail, pendingsession);
1354                   GNUNET_free(pendingsession);
1355                   break;
1356                 }
1357               pendingsession = pendingsession->next;
1358             }
1359
1360           //is something of this session in the fragment queue?
1361           fm = get_fragment_message_from_session(queue->content);
1362           free_fragment_message(plugin,fm);
1363
1364
1365           // remove PendingMessage
1366           pm = queue->content->pending_message;
1367           GNUNET_free(pm->msg);
1368           GNUNET_free(pm);
1369
1370           GNUNET_free(queue->content);
1371           GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1372           GNUNET_free(queue);
1373           plugin->session_count --;
1374
1375           return;
1376         }
1377       // try next
1378       queue = queue->next;
1379     }
1380 }
1381
1382
1383 /**
1384  * Convert the transports address to a nice, human-readable
1385  * format.
1386  *
1387  * @param cls closure
1388  * @param type name of the transport that generated the address
1389  * @param addr one of the addresses of the host, NULL for the last address
1390  *        the specific address format depends on the transport
1391  * @param addrlen length of the address
1392  * @param numeric should (IP) addresses be displayed in numeric form?
1393  * @param timeout after how long should we give up?
1394  * @param asc function to call on each string
1395  * @param asc_cls closure for asc
1396  */
1397 static void
1398 wlan_plugin_address_pretty_printer (void *cls,
1399                                     const char *type,
1400                                     const void *addr,
1401                                     size_t addrlen,
1402                                     int numeric,
1403                                     struct GNUNET_TIME_Relative timeout,
1404                                     GNUNET_TRANSPORT_AddressStringCallback
1405                                     asc, void *asc_cls)
1406 {
1407   char ret[92];
1408   const unsigned char * input;
1409   
1410   GNUNET_assert(cls !=NULL);
1411   if (addrlen != 6)
1412     {
1413       /* invalid address (MAC addresses have 6 bytes) */
1414       GNUNET_break (0);
1415       asc (asc_cls, NULL);
1416       return;
1417     }
1418   input = (const unsigned char*) addr;
1419   GNUNET_snprintf (ret, 
1420                    sizeof (ret),
1421                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1422                    PROTOCOL_PREFIX, 
1423                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1424   asc (asc_cls, ret);
1425 }
1426
1427
1428
1429 /**
1430  * Another peer has suggested an address for this
1431  * peer and transport plugin.  Check that this could be a valid
1432  * address.  If so, consider adding it to the list
1433  * of addresses.
1434  *
1435  * @param cls closure
1436  * @param addr pointer to the address
1437  * @param addrlen length of addr
1438  * @return GNUNET_OK if this is a plausible address for this peer
1439  *         and transport
1440  */
1441
1442
1443 static int
1444 wlan_plugin_address_suggested (void *cls,
1445                                    const void *addr,
1446                                    size_t addrlen)
1447 {
1448   //struct Plugin *plugin = cls;
1449
1450   /* check if the address is plausible; if so,
1451      add it to our list! */
1452
1453   GNUNET_assert(cls !=NULL);
1454   //FIXME mitm is not checked
1455   //Mac Adress has 6 bytes
1456   if (addrlen == 6){
1457     /* TODO check for bad addresses like milticast, broadcast, etc */
1458     return GNUNET_OK;
1459   } else {
1460     return GNUNET_SYSERR;
1461   }
1462
1463   return GNUNET_SYSERR;
1464 }
1465
1466
1467 /**
1468  * Function called for a quick conversion of the binary address to
1469  * a numeric address.  Note that the caller must not free the 
1470  * address and that the next call to this function is allowed
1471  * to override the address again.
1472  *
1473  * @param cls closure
1474  * @param addr binary address
1475  * @param addrlen length of the address
1476  * @return string representing the same address 
1477  */
1478 static const char* 
1479 wlan_plugin_address_to_string (void *cls,
1480                                const void *addr,
1481                                size_t addrlen)
1482 {
1483   char ret[92];
1484   const unsigned char * input;
1485   
1486   GNUNET_assert(cls !=NULL);
1487   if (addrlen != 6)
1488     {
1489       /* invalid address (MAC addresses have 6 bytes) */
1490       GNUNET_break (0);
1491       return NULL;
1492     }
1493   input = (const unsigned char*) addr;
1494   GNUNET_snprintf (ret, 
1495                    sizeof (ret),
1496                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1497                    PROTOCOL_PREFIX, 
1498                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1499   return GNUNET_strdup (ret);
1500 }
1501
1502
1503
1504
1505 /**
1506  * Function used for to process the data from the suid process
1507  */
1508 //TODO doxigen
1509
1510 static void
1511 wlan_process_helper (void *cls,
1512                       void *client,
1513                       const struct GNUNET_MessageHeader *hdr)
1514 {
1515   struct Plugin *plugin = cls;
1516   struct IeeeHeader * wlanIeeeHeader = NULL;
1517   struct Session * session = NULL;
1518   struct WlanHeader * wlanheader = NULL;
1519   struct FragmentationHeader * fh = NULL;
1520   struct FragmentMessage * fm = NULL;
1521   const struct GNUNET_MessageHeader * temp_hdr = NULL;
1522   const char * tempmsg = NULL;
1523   struct Session_light * session_light;
1524   struct AckQueue * ack;
1525   struct AckQueue * ack2;
1526   int pos = 0;
1527
1528
1529   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
1530     {
1531       //call wlan_process_helper with the message inside, later with wlan: analyze signal
1532       GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
1533       wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
1534
1535       session_light = GNUNET_malloc(sizeof(struct Session_light));
1536       memcpy(session_light->addr, wlanIeeeHeader->mac3, 6);
1537       session_light->session = search_session(plugin, session_light->addr);
1538
1539       //process only if it is an broadcast or for this computer both with the gnunet bssid
1540       //check for bssid
1541       if (memcmp(wlanIeeeHeader->mac2, macbc, sizeof(macbc)))
1542         {
1543           //check for broadcast or mac
1544           if (memcmp(wlanIeeeHeader->mac1, bc_all_mac, sizeof(bc_all_mac))
1545               || memcmp(wlanIeeeHeader->mac1, plugin->mac_address,
1546                   sizeof(plugin->mac_address)))
1547             {
1548               // process the inner data
1549             pos = 0;
1550             temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
1551               while (pos < hdr->size)
1552                 {
1553                   wlan_process_helper(plugin, &session_light,
1554                       temp_hdr);
1555                   pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
1556                 }
1557             }
1558         }
1559
1560     }
1561
1562
1563   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1564     {
1565       //TODO better DOS protection, error handling
1566       GNUNET_assert(client != NULL);
1567       session_light = (struct Session_light *) client;
1568       if (session_light->session == NULL){
1569         session_light->session = get_Session(plugin, session_light->addr);
1570       }
1571       GNUNET_assert(GNUNET_HELLO_get_id(
1572           (const struct GNUNET_HELLO_Message *) &hdr[1],
1573           &(session_light->session->target) ) != GNUNET_SYSERR);
1574
1575     }
1576
1577
1578   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1579     {
1580       GNUNET_assert(client != NULL);
1581       session_light = (struct Session_light *) client;
1582       if (session_light->session == NULL){
1583         session_light->session = search_session(plugin, session_light->addr);
1584       }
1585       session = session_light->session;
1586       wlanheader =(struct WlanHeader *) &hdr[1];
1587       tempmsg = (char*) &wlanheader[1];
1588       temp_hdr = ( const struct GNUNET_MessageHeader *) &wlanheader[1];
1589
1590       if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc){
1591         //wrong crc, dispose message
1592         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1593                                      "WLAN message crc was wrong\n");
1594         return;
1595       }
1596
1597       //if not in session list
1598       if (session == NULL){
1599
1600         //try if it is a hello message
1601         if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO){
1602           session = create_session(plugin, session_light->addr);
1603           session_light->session = session;
1604           GNUNET_assert(GNUNET_HELLO_get_id(
1605               (const struct GNUNET_HELLO_Message *) temp_hdr,
1606               &session->target ) != GNUNET_SYSERR);
1607
1608         } else {
1609           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1610                              "WLAN client not in session list and not a hello message\n");
1611           return;
1612         }
1613       }
1614       //"receive" the message
1615       plugin->env->receive(plugin, &session->target,
1616            temp_hdr, 1, session, session->addr, sizeof(session->addr));
1617     }
1618
1619   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1620     {
1621       GNUNET_assert(client != NULL);
1622       session_light = (struct Session_light *) client;
1623       if (session_light->session == NULL)
1624         {
1625           session_light->session = search_session(plugin, session_light->addr);
1626         }
1627       session = session_light->session;
1628
1629       fh = (struct FragmentationHeader *) &hdr[1];
1630       tempmsg = (char*) &fh[1];
1631
1632       //if not in session list
1633       if (session != NULL)
1634         {
1635           if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1636             {
1637               //wrong crc, dispose message
1638               GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1639                   "WLAN fragment crc was wrong\n");
1640               return;
1641             }
1642           else
1643             {
1644               //todo fragments to message
1645             }
1646         }
1647       else
1648         {
1649           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1650               "WLAN client not in session list and it is a fragment message\n");
1651           return;
1652         }
1653
1654     }
1655
1656   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1657     {
1658       GNUNET_assert(client != NULL);
1659       session_light = (struct Session_light *) client;
1660       if (session_light->session == NULL)
1661         {
1662           session_light->session = search_session(plugin, session_light->addr);
1663         }
1664       session = session_light->session;
1665       fh = (struct FragmentationHeader *) &hdr[1];
1666       if (fh->message_id == session->message_id_out)
1667         {
1668           fm = get_fragment_message_from_session(session);
1669           if (fm != NULL)
1670             {
1671               ack = GNUNET_malloc(sizeof(struct AckQueue));
1672               ack->fragment_num = fh->fragment_off_or_num;
1673               ack2 = fm->head;
1674               while (ack2!=NULL){
1675                 if (ack2->fragment_num != ack->fragment_num)
1676                     {
1677                       if (ack2->fragment_num > ack->fragment_num)
1678                         {
1679                           GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
1680                           //check if finished
1681                           check_finished_fragment(plugin, fm);
1682                         }
1683                     }
1684                   else
1685                     {
1686                       //double ack
1687                       return;
1688                     }
1689                 ack2 = ack2->next;
1690               }
1691               GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
1692               //should never happen but...
1693               check_finished_fragment(plugin, fm);
1694             }
1695           else
1696             {
1697               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1698                   "WLAN fragment not in fragment list but id is right\n");
1699               return;
1700             }
1701
1702         }
1703
1704     }
1705
1706   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
1707     {
1708       //TODO Control
1709       if (ntohs(hdr->size) == 6)
1710         {
1711           plugin->mac_address = GNUNET_malloc(6);
1712           memcpy(plugin->mac_address, &hdr[1], 6);
1713           GNUNET_log(
1714               GNUNET_ERROR_TYPE_DEBUG,
1715               "Notifying transport of address %s\n",
1716               wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1717           plugin->env->notify_address(plugin->env->cls, "wlan",
1718               &plugin->mac_address, sizeof(plugin->mac_address),
1719               GNUNET_TIME_UNIT_FOREVER_REL);
1720         }
1721       else
1722         {
1723           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
1724               plugin->mac_address);
1725         }
1726
1727     }
1728
1729
1730   else
1731     {
1732       // TODO Wrong data?
1733     }
1734 }
1735
1736
1737 static void
1738 wlan_plugin_helper_read (void *cls,
1739                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1740 {
1741   struct Plugin *plugin = cls;
1742   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1743
1744   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
1745   ssize_t bytes;
1746
1747   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1748     return;
1749
1750   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
1751                                  mybuf, sizeof(mybuf));
1752   if (bytes <= 0)
1753     {
1754 #if DEBUG_wlan
1755       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1756                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1757 #endif
1758       return;
1759     }
1760   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1761                             mybuf, bytes, GNUNET_NO, GNUNET_NO);
1762
1763   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1764   plugin->server_read_task =
1765   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1766                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1767 }
1768
1769
1770 /**
1771  * Start the gnunet-wlan-helper process.
1772  *
1773  * @param plugin the transport plugin
1774  *
1775  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1776  */
1777 static int
1778 wlan_transport_start_wlan_helper(struct Plugin *plugin)
1779 {
1780
1781   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1782   if (plugin->server_stdout == NULL)
1783     return GNUNET_SYSERR;
1784
1785   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
1786   if (plugin->server_stdin == NULL)
1787     return GNUNET_SYSERR;
1788
1789 #if DEBUG_wlan
1790   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1791       "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1792 #endif
1793   /* Start the server process */
1794   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
1795       plugin->server_stdout, "gnunet-transport-wlan-helper",
1796       "gnunet-transport-wlan-helper", plugin->interface, NULL);
1797   if (plugin->server_proc == NULL)
1798     {
1799 #if DEBUG_wlan
1800       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1801           "Failed to start gnunet-wlan-helper process\n");
1802 #endif
1803       return GNUNET_SYSERR;
1804     }
1805   /* Close the write end of the read pipe */
1806   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1807
1808   /* Close the read end of the write pipe */
1809   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1810
1811   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
1812       GNUNET_DISK_PIPE_END_READ);
1813   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
1814       GNUNET_DISK_PIPE_END_WRITE);
1815
1816   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1817   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
1818       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
1819       &wlan_plugin_helper_read, plugin);
1820   return GNUNET_YES;
1821 }
1822
1823
1824
1825 /**
1826  * Entry point for the plugin.
1827  *
1828  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1829  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1830  */
1831 void *
1832 libgnunet_plugin_transport_wlan_init (void *cls)
1833 {
1834   struct GNUNET_SERVICE_Context *service;
1835   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1836   struct GNUNET_TRANSPORT_PluginFunctions *api;
1837   struct Plugin *plugin;
1838
1839   GNUNET_assert(cls !=NULL);
1840
1841   service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
1842         if (service == NULL){
1843                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1844                            _("Failed to start service for `%s' transport plugin.\n"),
1845                            "wlan");
1846                 return NULL;
1847         }
1848
1849   plugin = GNUNET_malloc (sizeof (struct Plugin));
1850   plugin->env = env;
1851   plugin->pendingsessions = 0;
1852   plugin->session_count = 0;
1853   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1854   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1855   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1856
1857   wlan_transport_start_wlan_helper(plugin);
1858   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1859
1860   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1861   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1862
1863   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1864   api->cls = plugin;
1865   api->send = &wlan_plugin_send;
1866   api->disconnect = &wlan_plugin_disconnect;
1867   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1868   api->check_address = &wlan_plugin_address_suggested;
1869   api->address_to_string = &wlan_plugin_address_to_string;
1870
1871
1872   start_next_message_id();
1873
1874   return api;
1875 }
1876
1877
1878 /**
1879  * Exit point from the plugin.
1880  */
1881 //TODO doxigen
1882 //fixme cleanup
1883 void *
1884 libgnunet_plugin_transport_wlan_done (void *cls)
1885 {
1886   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1887   struct Plugin *plugin = api->cls;
1888
1889   GNUNET_SERVER_mst_destroy(plugin->consoltoken);
1890
1891   GNUNET_assert(cls !=NULL);
1892
1893   GNUNET_free_non_null(plugin->mac_address);
1894   GNUNET_free (plugin);
1895   GNUNET_free (api);
1896   return NULL;
1897 }
1898
1899 /* end of plugin_transport_wlan.c */