fixed coverity bug #10042
[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    * encapsulation to the local wlan server prog
100    */
101
102   struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
103
104
105   /**
106    * stdout pipe handle for the gnunet-wlan-helper process
107    */
108   struct GNUNET_DISK_PipeHandle *server_stdout;
109
110   /**
111    * stdout file handle for the gnunet-wlan-helper process
112    */
113   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
114
115   /**
116    * stdin pipe handle for the gnunet-wlan-helper process
117    */
118   struct GNUNET_DISK_PipeHandle *server_stdin;
119
120   /**
121    * stdin file handle for the gnunet-wlan-helper process
122    */
123   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
124
125   /**
126    * ID of select gnunet-nat-server std read task
127    */
128   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
129
130   /**
131      * ID of select gnunet-nat-server std read task
132      */
133   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
134
135   /**
136    * The process id of the server process (if behind NAT)
137    */
138   struct GNUNET_OS_Process *server_proc;
139
140   /**
141    * The interface of the wlan card given to us by the user.
142    */
143   char *interface;
144
145   /**
146    * The mac_address of the wlan card given to us by the helper.
147    */
148   char *mac_address;
149
150   /**
151    * Sessions currently pending for transmission
152    * to this peer, if any.
153    */
154   struct Sessionqueue * pending_Sessions;
155
156   /**
157     * Sessions currently pending for transmission
158     * to this peer (tail), if any.
159     */
160   struct Sessionqueue * pending_Sessions_tail;
161
162   /**
163    * number of pending sessions
164    */
165   unsigned int pendingsessions;
166
167   /**
168    * Messages in the fragmentation queue, head
169    */
170
171   struct FragmentMessage * pending_Fragment_Messages_head;
172
173   /**
174    * Messages in the fragmentation queue, tail
175    */
176
177   struct FragmentMessage * pending_Fragment_Messages_tail;
178
179   /**
180      * number of pending fragment message
181      */
182
183   unsigned int pending_fragment_messages;
184
185 };
186
187 //TODO doxigen
188
189 struct Sessionqueue
190 {
191         struct Sessionqueue * next;
192         struct Sessionqueue * prev;
193         struct Session * content;
194 };
195
196 //TODO doxigen
197
198 struct AckQueue
199 {
200         struct AckQueue * next;
201         struct AckQueue * prev;
202         int fragment_num;
203 };
204
205 /**
206  * Information kept for each message that is yet to
207  * be transmitted.
208  */
209 struct PendingMessage
210 {
211
212   /**
213    * The pending message
214    */
215   char *msg;
216
217   /**
218    * Continuation function to call once the message
219    * has been sent.  Can be NULL if there is no
220    * continuation to call.
221    */
222   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
223
224   /**
225    * Cls for transmit_cont
226    */
227   void * transmit_cont_cls;
228
229   /**
230    * Timeout value for the pending message.
231    */
232   struct GNUNET_TIME_Absolute timeout;
233
234   /**
235    * Size of the message
236    */
237   size_t message_size;
238
239 };
240
241 /**
242  * Session handle for connections.
243  */
244 struct Session
245 {
246
247   /**
248    * API requirement.
249    */
250   struct SessionHeader header;
251
252   /**
253    * Pointer to the global plugin struct.
254    */
255   struct Plugin *plugin;
256
257   /**
258    * Message currently pending for transmission
259    * to this peer, if any.
260    */
261   struct PendingMessage *pending_message;
262
263   /**
264    * To whom are we talking to (set to our identity
265    * if we are still waiting for the welcome message)
266    */
267   struct GNUNET_PeerIdentity target;
268
269   /**
270    * encapsulation of the data
271    */
272   //struct GNUNET_SERVER_MessageStreamTokenizer * datatoken;
273
274   /**
275    * peer mac address
276    */
277   char addr[6];
278
279   /**
280    * Address of the other peer (either based on our 'connect'
281    * call or on our 'accept' call).
282    */
283   void *connect_addr;
284
285   /**
286    * Last activity on this connection.  Used to select preferred
287    * connection.
288    */
289   struct GNUNET_TIME_Absolute last_activity;
290
291   /**
292    * current number for message incoming, to distinguish between the messages
293    */
294   uint32_t message_id_in;
295
296   /**
297    * current number for message outgoing, to distinguish between the messages
298    */
299   uint32_t message_id_out;
300
301   /**
302    * does this session have a message in the fragment queue
303    */
304
305   int has_fragment;
306
307 };
308
309
310
311
312 struct FragmentMessage
313 {
314         /**
315          * Session this message belongs to
316          */
317
318         struct Session *session;
319
320         /**
321         * This is a doubly-linked list.
322         */
323         struct FragmentMessage *next;
324
325         /**
326         * This is a doubly-linked list.
327         */
328         struct FragmentMessage *prev;
329
330         /**
331         * The pending message
332         */
333         char *msg;
334
335         /**
336         * Timeout value for the pending message.
337         */
338         struct GNUNET_TIME_Absolute timeout;
339
340         /**
341         * Timeout value for the pending fragments.
342         * Stores the time when the next msg fragment ack has to be received
343         */
344         struct GNUNET_TIME_Absolute next_ack;
345
346         /**
347         * Sorted queue with the acks received for fragments; head
348         */
349
350         struct AckQueue * head;
351
352         /**
353         * Sorted queue with the acks received for fragments; tail
354         */
355
356         struct AckQueue * tail;
357
358         /**
359         * Size of the message
360         */
361         size_t message_size;
362
363         /**
364         * pos / next fragment number in the message, for fragmentation/segmentation,
365         * some acks can be missing but there is still time
366         */
367         uint32_t message_pos;
368
369 };
370
371 /**
372  * Header for messages which need fragmentation
373  */
374 struct WlanHeader
375 {
376
377   struct GNUNET_MessageHeader header;
378
379   /**
380    * checksum/error correction
381    */
382   uint32_t crc GNUNET_PACKED;
383
384   /**
385    * To whom are we talking to (set to our identity
386    * if we are still waiting for the welcome message)
387    */
388   struct GNUNET_PeerIdentity target;
389
390   // followed by payload
391
392 };
393
394 /**
395  * Header for messages which need fragmentation
396  */
397 struct FragmentationHeader
398 {
399
400   struct GNUNET_MessageHeader header;
401
402   /**
403    * To whom are we talking to (set to our identity
404    * if we are still waiting for the welcome message)
405    */
406   // struct GNUNET_PeerIdentity target GNUNET_PACKED;
407
408   /**
409    * ID of message, to distinguish between the messages, picked randomly.
410    */
411   uint32_t message_id GNUNET_PACKED;
412
413   /**
414    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
415    */
416   uint16_t fragment_off_or_num GNUNET_PACKED;
417
418   /**
419    * CRC of fragment (for error checking)
420    */
421   uint16_t message_crc GNUNET_PACKED;
422
423   /**
424    * Flags
425    * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
426    * // 0x2 has data (not only ack)
427    * // 0x4 last fragment of message
428    * // 0x8 new message
429    */
430   //  uint32_t flags GNUNET_PACKED;
431
432   /**
433    * checksum/error correction
434    */
435   // uint32_t crc GNUNET_PACKED;
436
437   // followed by payload unless ACK
438
439 };
440
441 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
442
443 int getRadiotapHeader (struct RadiotapHeader * Header);
444 int getWlanHeader (struct IeeeHeader * Header);
445 static int wlan_plugin_address_suggested (void *cls,
446                                    const void *addr,
447                                    size_t addrlen);
448 uint16_t getcrc16 (const char *msgbuf, size_t msgbuf_size);
449 static void do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
450 static void check_fragment_queue (struct Plugin * plugin);
451
452 /**
453  * get the next message number, at the moment just a random one
454  *
455  */
456 //TODO doxigen
457 uint32_t
458 get_next_message_id()
459 {
460         return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
461 }
462
463 /**
464  * start next message number generator
465  */
466 //TODO doxigen
467 void
468 start_next_message_id()
469 {
470         //GNUNET_CRYPTO_random_init;
471 }
472
473
474 /**
475  * get Session from address
476  *
477  */
478 //TODO doxigen
479 //TODO add other possibilities to find the right session (are there other?)
480 static struct Session *
481 get_Session (struct Plugin *plugin,
482              const char * addr)
483 {
484         struct Sessionqueue * queue = plugin->sessions;
485         struct Sessionqueue * lastitem = NULL;
486
487
488         //just look at all the session for the needed one
489         while (queue != NULL){
490                 // content is never NULL
491                 GNUNET_assert (queue->content == NULL);
492                 char * addr2 = queue->content->addr;
493                 if (memcmp(addr, addr2, 6) == 0)
494                   {
495                     //sesion found
496                     return queue->content;
497                   }
498                 // try next
499                 lastitem = queue;
500                 queue = queue->next;
501         }
502         // new session
503         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
504
505         GNUNET_CONTAINER_DLL_insert(plugin->sessions, plugin->sessions_tail, queue);
506
507         queue->content = GNUNET_malloc (sizeof (struct Session));
508         queue->content->plugin = plugin;
509         memcpy(queue->content->addr, addr, 6);
510         queue->content->message_id_out = get_next_message_id();
511         queue->content->has_fragment = 0;
512
513         //queue welcome message for new sessions, not realy needed
514         //struct WelcomeMessage welcome;
515         struct PendingMessage *pm;
516         pm = GNUNET_malloc (sizeof (struct PendingMessage));
517         pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
518         pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
519         //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
520         //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
521         //welcome.clientIdentity = *plugin->env->my_identity;
522         memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
523         pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
524         queue->content->pending_message = pm;
525         plugin->pendingsessions ++;
526         GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
527
528         check_fragment_queue(plugin);
529
530         return queue->content;
531
532 }
533
534 /**
535  * Queue the session to send data
536  */
537 //TODO doxigen
538 static void
539 queue_Session (struct Plugin *plugin,
540                 struct Session * session)
541 {
542         struct Sessionqueue * queue = plugin->pending_Sessions;
543         struct Sessionqueue * lastitem = NULL;
544
545         while (queue != NULL){
546                 // content is never NULL
547                 GNUNET_assert (queue->content == NULL);
548                 // is session already in queue?
549                 if (session == queue->content){
550                         return;
551                 }
552                 // try next
553                 lastitem = queue;
554                 queue = queue->next;
555         }
556
557         // Session is not in the queue
558
559         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
560         queue->content = session;
561
562         //insert at the tail
563         GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
564                         plugin->pending_Sessions_tail,
565                         plugin->pending_Sessions_tail, queue);
566         plugin->pendingsessions ++;
567
568 }
569
570 //TODO doxigen
571 static void
572 free_acks (struct FragmentMessage * pm){
573         struct AckQueue * fq;
574         while (pm->head != NULL){
575                 fq = pm->head;
576                 GNUNET_CONTAINER_DLL_remove(pm->head, pm->tail, fq);
577                 GNUNET_free(fq);
578         }
579 }
580
581 //TODO doxigen
582 static void
583 delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc){
584         struct Plugin * plugin = cls;
585         plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
586
587         if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
588             return;
589
590         // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
591         plugin->server_write_task
592                 = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
593                                                                                         plugin->server_stdin_handle,
594                                                                                    &do_transmit,
595                                                                                    plugin);
596 }
597
598
599 //TODO doxigen
600 struct GNUNET_TIME_Relative
601 get_next_frag_timeout (struct FragmentMessage * fm)
602 {
603         return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
604 }
605
606 //TODO doxigen
607 /**
608  * Function to get the timeout value for acks for this session
609  */
610
611 struct GNUNET_TIME_Relative
612 get_ack_timeout (struct FragmentMessage * fm){
613         return FRAGMENT_TIMEOUT;
614 }
615
616 //TODO doxigen
617 /**
618  * Function to set the timer for the next timeout of the fragment queue
619  */
620 static void
621 check_next_fragment_timeout (struct Plugin * plugin){
622         struct FragmentMessage * fm;
623         if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK){
624                 GNUNET_SCHEDULER_cancel(plugin->server_write_task);
625         }
626         fm = plugin->pending_Fragment_Messages_head;
627         if (fm != NULL){
628                 plugin->server_write_task = GNUNET_SCHEDULER_add_delayed(get_next_frag_timeout(fm), &delay_fragment_task, plugin);
629         }
630 }
631
632 //TODO doxigen
633 /**
634  * Function to get the next queued Session, removes the session from the queue
635  */
636
637 static struct Session *
638 get_next_queue_Session (struct Plugin * plugin){
639         struct Session * session;
640         struct Sessionqueue * sessionqueue;
641         struct Sessionqueue * sessionqueue_alt;
642         struct PendingMessage * pm;
643         sessionqueue = plugin->pending_Sessions;
644         while (sessionqueue != NULL){
645                 session = sessionqueue->content;
646                 pm = session->pending_message;
647
648                 //check for message timeout
649                 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
650                         //check if session has no message in the fragment queue
651                         if (! session->has_fragment){
652                                 plugin->pendingsessions --;
653                                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
654                                                 plugin->pending_Sessions_tail, sessionqueue);
655                                 GNUNET_free(sessionqueue);
656
657                                 return session;
658                         } else {
659                                 sessionqueue = sessionqueue->next;
660                         }
661                 } else {
662
663                         session->pending_message = NULL;
664                         //call the cont func that it did not work
665                         if (pm->transmit_cont != NULL)
666                           pm->transmit_cont (pm->transmit_cont_cls,
667                                                 &(session->target), GNUNET_SYSERR);
668                         GNUNET_free(pm->msg);
669                         GNUNET_free(pm);
670
671                         sessionqueue_alt = sessionqueue;
672                         sessionqueue = sessionqueue->next;
673                         plugin->pendingsessions --;
674                         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
675                                         plugin->pending_Sessions_tail, sessionqueue_alt);
676
677                         GNUNET_free(sessionqueue_alt);
678
679                 }
680
681
682         }
683         return NULL;
684 }
685
686 //TODO doxigen
687 /**
688  * Function to sort the message into the message fragment queue
689  */
690 static void
691 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
692         struct FragmentMessage * fm2;
693         //sort into the list at the right position
694
695         fm2 = plugin->pending_Fragment_Messages_head;
696
697         while (fm2 != NULL){
698                 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
699                         break;
700                 } else {
701                         fm2 = fm2->next;
702                 }
703         }
704
705         GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
706                         plugin->pending_Fragment_Messages_tail,fm2,fm);
707 }
708
709 //TODO doxigen
710 /**
711  * Function to check if there is some space in the fragment queue
712  */
713
714 static void
715 check_fragment_queue (struct Plugin * plugin){
716         struct Session * session;
717         struct FragmentMessage * fm;
718
719         struct PendingMessage * pm;
720
721         if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
722                 session = get_next_queue_Session(plugin);
723                 if (session != NULL){
724                         pm = session->pending_message;
725                         session->pending_message = NULL;
726                         session->has_fragment = 1;
727                         GNUNET_assert(pm != NULL);
728
729                         fm = GNUNET_malloc(sizeof(struct FragmentMessage));
730                         fm->message_size = pm->message_size;
731                         fm->msg = pm->msg;
732                         fm->session = session;
733                         fm->timeout.abs_value = pm->timeout.abs_value;
734                         fm->message_pos = 0;
735                         fm->next_ack = GNUNET_TIME_absolute_get();
736
737                         if (pm->transmit_cont != NULL)
738                                   pm->transmit_cont (pm->transmit_cont_cls,
739                                                         &(session->target), GNUNET_OK);
740                         GNUNET_free(pm);
741
742                         sort_fragment_into_queue(plugin,fm);
743                         plugin->pending_fragment_messages ++;
744
745                         //generate new message id
746                         session->message_id_out = get_next_message_id();
747
748                         //check if timeout changed
749                         check_next_fragment_timeout(plugin);
750                 }
751         }
752 }
753
754 /**
755  * Function called to when wlan helper is ready to get some data
756  *
757  * @param cls closure
758  * @param GNUNET_SCHEDULER_TaskContext
759  */
760
761 static void
762 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
763 {
764
765   struct Plugin * plugin = cls;
766   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
767
768   ssize_t bytes;
769
770   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
771     return;
772
773   struct Session * session;
774   struct FragmentMessage * fm;
775   struct IeeeHeader * wlanheader;
776   struct RadiotapHeader * radioHeader;
777   struct GNUNET_MessageHeader * msgheader;
778   struct FragmentationHeader fragheader;
779   uint16_t size = 0;
780   const char * copystart = NULL;
781   uint16_t copysize = 0;
782   uint copyoffset = 0;
783   struct AckQueue * akt = NULL;
784   //int exit = 0;
785
786   fm = plugin->pending_Fragment_Messages_head;
787   GNUNET_assert(fm != NULL);
788   session = fm->session;
789   GNUNET_assert(session != NULL);
790
791   // test if message timed out
792   if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
793           free_acks(fm);
794           GNUNET_assert(plugin->pending_fragment_messages > 0);
795           plugin->pending_fragment_messages --;
796           GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
797                           plugin->pending_Fragment_Messages_tail, fm);
798
799           GNUNET_free(fm->msg);
800
801           GNUNET_free(fm);
802           check_fragment_queue(plugin);
803   } else {
804
805           if (fm->message_size > WLAN_MTU) {
806                 size += sizeof(struct FragmentationHeader);
807                 // check/set for retransmission
808                 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
809
810                         // be positive and try again later :-D
811                         fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
812                         // find first missing fragment
813                         akt = fm->head;
814                         fm->message_pos = 0;
815
816                         //test if ack 0 was already received
817                         while (akt != NULL){
818                                 //if fragment is present, take next
819                                 if (akt->fragment_num == fm->message_pos) {
820                                         fm->message_pos ++;
821                                 }
822                                 //next ack is bigger then the fragment number
823                                 //in case there is something like this: (acks) 1, 2, 5, 6, ...
824                                 //and we send 3 again, the next number should be 4
825                                 else if (akt->fragment_num > fm->message_pos) {
826                                         break;
827                                 }
828
829                                 akt = akt->next;
830
831                         }
832
833
834                 }
835
836                 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
837                 fragheader.fragment_off_or_num = htons(fm->message_pos);
838                 fragheader.message_id = htonl(session->message_id_out);
839
840                 // start should be smaller then the packet size
841                 GNUNET_assert(copyoffset < fm->message_size);
842                 copystart = fm->msg + copyoffset;
843
844                 //size of the fragment is either the MTU - overhead
845                 //or the missing part of the message in case this is the last fragment
846                 copysize = GNUNET_MIN(fm->message_size - copyoffset,
847                                 WLAN_MTU - sizeof(struct FragmentationHeader));
848                 fragheader.header.size = htons(copysize);
849                 fragheader.header.type = GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT;
850
851
852                 //get the next missing fragment
853                 akt = fm->head;
854                 fm->message_pos ++;
855
856                 //test if ack was already received
857                 while (akt != NULL){
858                         //if fragment is present, take next
859                         if (akt->fragment_num == fm->message_pos) {
860                                 fm->message_pos ++;
861                         }
862                         //next ack is bigger then the fragment number
863                         //in case there is something like this: (acks) 1, 2, 5, 6, ...
864                         //and we send 3 again, the next number should be 4
865                         else if (akt->fragment_num > fm->message_pos) {
866                                 break;
867                         }
868
869                         akt = akt->next;
870                 }
871           } else {
872                 // there is no need to split
873                 copystart = fm->msg;
874                 copysize = fm->message_size;
875           }
876
877         size += copysize;
878         size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
879                 + sizeof(struct GNUNET_MessageHeader);
880         msgheader = GNUNET_malloc(size);
881         msgheader->size = htons(size - sizeof(struct GNUNET_MessageHeader));
882         msgheader->type = GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA;
883
884         radioHeader = (struct RadiotapHeader*) &msgheader[1];
885         getRadiotapHeader(radioHeader);
886
887         wlanheader = (struct IeeeHeader *) &radioHeader[1];
888         getWlanHeader(wlanheader);
889
890
891         //could be faster if content is just send and not copyed before
892         //fragmentheader is needed
893         if (fm->message_size > WLAN_MTU){
894                 fragheader.message_crc = htons(getcrc16(copystart, copysize));
895                 memcpy(&wlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
896                 memcpy(&wlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
897         } else {
898                 memcpy(&wlanheader[1],copystart,copysize);
899         }
900
901         bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
902         GNUNET_assert(bytes == size);
903
904         //check if this was the last fragment of this message, if true then queue at the end of the list
905         if (copysize + copyoffset >= fm->message_size){
906                 GNUNET_assert(copysize + copyoffset == fm->message_size);
907
908                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
909                                 plugin->pending_Fragment_Messages_tail, fm);
910
911                 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
912                                 plugin->pending_Fragment_Messages_tail, fm);
913                 // if fragments have opimized timeouts
914                 //sort_fragment_into_queue(plugin,fm);
915
916         }
917         check_next_fragment_timeout(plugin);
918
919   }
920 }
921
922
923 /**
924  * 32bit CRC
925  *
926  * @param msgbuf pointer tor the data
927  * @param msgbuf_size size of the data
928  *
929  * @return 32bit crc value
930  */
931
932 uint32_t
933 getcrc32 (const char *msgbuf,
934                   size_t msgbuf_size){
935         //TODO calc some crc
936         return 0;
937 }
938
939 /**
940  * 16bit CRC
941  *
942  * @param msgbuf pointer tor the data
943  * @param msgbuf_size size of the data
944  *
945  * @return 16bit crc value
946  */
947
948 uint16_t
949 getcrc16 (const char *msgbuf,
950                   size_t msgbuf_size){
951         //TODO calc some crc
952         return 0;
953 }
954
955 /**
956  * Function that can be used by the transport service to transmit
957  * a message using the plugin.
958  *
959  * @param cls closure
960  * @param target who should receive this message
961  * @param priority how important is the message
962  * @param msgbuf the message to transmit
963  * @param msgbuf_size number of bytes in 'msgbuf'
964  * @param timeout when should we time out 
965  * @param session which session must be used (or NULL for "any")
966  * @param addr the address to use (can be NULL if the plugin
967  *                is "on its own" (i.e. re-use existing TCP connection))
968  * @param addrlen length of the address in bytes
969  * @param force_address GNUNET_YES if the plugin MUST use the given address,
970  *                otherwise the plugin may use other addresses or
971  *                existing connections (if available)
972  * @param cont continuation to call once the message has
973  *        been transmitted (or if the transport is ready
974  *        for the next transmission call; or if the
975  *        peer disconnected...)
976  * @param cont_cls closure for cont
977  * @return number of bytes used (on the physical network, with overheads);
978  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
979  *         and does NOT mean that the message was not transmitted (DV)
980  */
981 static ssize_t
982 wlan_plugin_send (void *cls,
983                   const struct GNUNET_PeerIdentity * target,
984                   const char *msgbuf,
985                   size_t msgbuf_size,
986                   unsigned int priority,
987                   struct GNUNET_TIME_Relative timeout,
988                   struct Session *session,
989                   const void *addr,
990                   size_t addrlen,
991                   int force_address,
992                   GNUNET_TRANSPORT_TransmitContinuation cont,
993                   void *cont_cls)
994 {
995   struct Plugin * plugin = cls;
996   struct PendingMessage * newmsg = NULL;
997   struct WlanHeader * wlanheader = NULL;
998   //check if msglen > 0
999   GNUNET_assert(msgbuf_size > 0);
1000
1001   //get session if needed
1002   if (session == NULL) {
1003           if ( wlan_plugin_address_suggested(plugin , addr, addrlen) == GNUNET_OK){
1004                   session = get_Session(plugin, addr);
1005           } else {
1006                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1007                                         _("Wlan Address len %d is wrong\n"),
1008                                          addrlen);
1009                   return -1;
1010           }
1011   }
1012
1013   //TODO target "problem" not solved
1014   session->target = *target;
1015
1016   //queue message:
1017   //first queue session
1018   queue_Session(plugin, session);
1019
1020   //queue message in session
1021   if (session->pending_message == NULL){
1022         newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1023         (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1024         wlanheader = (struct WlanHeader *) newmsg->msg;
1025         //copy msg to buffer, not fragmented / segmented yet, but with message header
1026         wlanheader->header.size = htons(msgbuf_size);
1027         wlanheader->header.type = GNUNET_MESSAGE_TYPE_WLAN_DATA;
1028         wlanheader->target = *target;
1029         wlanheader->crc = getcrc32(msgbuf, msgbuf_size);
1030         memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1031         newmsg->transmit_cont = cont;
1032         newmsg->transmit_cont_cls = cont_cls;
1033         newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1034         newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1035   } else {
1036           //TODO if message is send while hello is still pending, other cases should not occur
1037   }
1038   check_fragment_queue(plugin);
1039   //FIXME not the correct size
1040   return msgbuf_size;
1041
1042 }
1043
1044
1045
1046 /**
1047  * Function that can be used to force the plugin to disconnect
1048  * from the given peer and cancel all previous transmissions
1049  * (and their continuation).
1050  *
1051  * @param cls closure
1052  * @param target peer from which to disconnect
1053  */
1054 static void
1055 wlan_plugin_disconnect (void *cls,
1056                             const struct GNUNET_PeerIdentity *target)
1057 {
1058         struct Plugin *plugin = cls;
1059         struct Sessionqueue * queue = plugin->sessions;
1060         struct Sessionqueue * lastitem = NULL;
1061         struct PendingMessage * pm;
1062
1063         // just look at all the session for the needed one
1064         while (queue != NULL){
1065                 // content is never NULL
1066                 GNUNET_assert (queue->content == NULL);
1067                 if (memcmp(target, &(queue->content->target), sizeof(struct GNUNET_PeerIdentity)) == 0)
1068                   {
1069                         // session found
1070                         // remove PendingMessage
1071                         pm = queue->content->pending_message;
1072                         GNUNET_free(pm->msg);
1073                         GNUNET_free(pm);
1074
1075                         GNUNET_free(queue->content);
1076                         GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1077                         GNUNET_free(queue);
1078
1079                         return;
1080                   }
1081                 // try next
1082                 lastitem = queue;
1083                 queue = queue->next;
1084         }
1085 }
1086
1087
1088 /**
1089  * Convert the transports address to a nice, human-readable
1090  * format.
1091  *
1092  * @param cls closure
1093  * @param type name of the transport that generated the address
1094  * @param addr one of the addresses of the host, NULL for the last address
1095  *        the specific address format depends on the transport
1096  * @param addrlen length of the address
1097  * @param numeric should (IP) addresses be displayed in numeric form?
1098  * @param timeout after how long should we give up?
1099  * @param asc function to call on each string
1100  * @param asc_cls closure for asc
1101  */
1102 static void
1103 wlan_plugin_address_pretty_printer (void *cls,
1104                                     const char *type,
1105                                     const void *addr,
1106                                     size_t addrlen,
1107                                     int numeric,
1108                                     struct GNUNET_TIME_Relative timeout,
1109                                     GNUNET_TRANSPORT_AddressStringCallback
1110                                     asc, void *asc_cls)
1111 {
1112   char ret[92];
1113   const unsigned char * input;
1114   
1115   GNUNET_assert(cls !=NULL);
1116   if (addrlen != 6)
1117     {
1118       /* invalid address (MAC addresses have 6 bytes) */
1119       GNUNET_break (0);
1120       asc (asc_cls, NULL);
1121       return;
1122     }
1123   input = (const unsigned char*) addr;
1124   GNUNET_snprintf (ret, 
1125                    sizeof (ret),
1126                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1127                    PROTOCOL_PREFIX, 
1128                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1129   asc (asc_cls, ret);
1130 }
1131
1132
1133
1134 /**
1135  * Another peer has suggested an address for this
1136  * peer and transport plugin.  Check that this could be a valid
1137  * address.  If so, consider adding it to the list
1138  * of addresses.
1139  *
1140  * @param cls closure
1141  * @param addr pointer to the address
1142  * @param addrlen length of addr
1143  * @return GNUNET_OK if this is a plausible address for this peer
1144  *         and transport
1145  */
1146
1147
1148 static int
1149 wlan_plugin_address_suggested (void *cls,
1150                                    const void *addr,
1151                                    size_t addrlen)
1152 {
1153   //struct Plugin *plugin = cls;
1154
1155   /* check if the address is plausible; if so,
1156      add it to our list! */
1157
1158   GNUNET_assert(cls !=NULL);
1159   //FIXME mitm is not checked
1160   //Mac Adress has 6 bytes
1161   if (addrlen == 6){
1162     /* TODO check for bad addresses like milticast, broadcast, etc */
1163     return GNUNET_OK;
1164   } else {
1165     return GNUNET_SYSERR;
1166   }
1167
1168   return GNUNET_SYSERR;
1169 }
1170
1171
1172 /**
1173  * Function called for a quick conversion of the binary address to
1174  * a numeric address.  Note that the caller must not free the 
1175  * address and that the next call to this function is allowed
1176  * to override the address again.
1177  *
1178  * @param cls closure
1179  * @param addr binary address
1180  * @param addrlen length of the address
1181  * @return string representing the same address 
1182  */
1183 static const char* 
1184 wlan_plugin_address_to_string (void *cls,
1185                                const void *addr,
1186                                size_t addrlen)
1187 {
1188   char ret[92];
1189   const unsigned char * input;
1190   
1191   GNUNET_assert(cls !=NULL);
1192   if (addrlen != 6)
1193     {
1194       /* invalid address (MAC addresses have 6 bytes) */
1195       GNUNET_break (0);
1196       return NULL;
1197     }
1198   input = (const unsigned char*) addr;
1199   GNUNET_snprintf (ret, 
1200                    sizeof (ret),
1201                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1202                    PROTOCOL_PREFIX, 
1203                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1204   return GNUNET_strdup (ret);
1205 }
1206
1207
1208
1209 /**
1210  * Function used for to process the data from the suid process
1211  */
1212 //TODO doxigen
1213
1214 static void
1215 wlan_process_helper (void *cls,
1216                       void *client,
1217                       const struct GNUNET_MessageHeader *hdr)
1218 {
1219   struct Plugin *plugin = cls;
1220   if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA){
1221     //TODO DATA
1222   } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT){
1223     //TODO ADV
1224   } else if (hdr->type == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL){
1225     //TODO Control
1226     if (hdr->size == 6){
1227       plugin->mac_address = GNUNET_malloc(6);
1228       memcpy(plugin->mac_address, &hdr[1],6);
1229       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying transport of address %s\n", wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1230       plugin->env->notify_address (plugin->env->cls,
1231                                       "wlan",
1232                                       &plugin->mac_address, sizeof(plugin->mac_address),
1233                                       GNUNET_TIME_UNIT_FOREVER_REL);
1234     } else {
1235       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n", plugin->mac_address);
1236     }
1237
1238
1239   } else {
1240     // TODO Wrong data?
1241   }
1242 }
1243
1244
1245 static void
1246 wlan_plugin_helper_read (void *cls,
1247                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1248 {
1249   struct Plugin *plugin = cls;
1250   char mybuf[WLAN_MTU]; 
1251   ssize_t bytes;
1252
1253   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1254     return;
1255   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
1256                                  mybuf, sizeof(mybuf));
1257   if (bytes <= 0)
1258     {
1259 #if DEBUG_TCP_NAT
1260       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1261                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1262 #endif
1263       return;
1264     }
1265   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1266                             mybuf, bytes, 0, GNUNET_NO);
1267
1268 }
1269
1270
1271 /**
1272  * Start the gnunet-wlan-helper process.
1273  *
1274  * @param plugin the transport plugin
1275  *
1276  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1277  */
1278 static int
1279 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1280 {
1281
1282   plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1283   if (plugin->server_stdout == NULL)
1284     return GNUNET_SYSERR;
1285
1286   plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1287     if (plugin->server_stdin == NULL)
1288       return GNUNET_SYSERR;
1289
1290 #if DEBUG_TCP_NAT
1291   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1292                    "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1293 #endif
1294   /* Start the server process */
1295   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin, plugin->server_stdout, "gnunet-transport-wlan-helper", "gnunet-transport-wlan-helper", plugin->interface, NULL);
1296   if (plugin->server_proc == NULL)
1297     {
1298 #if DEBUG_TCP_NAT
1299     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1300                      "Failed to start gnunet-wlan-helper process\n");
1301 #endif
1302       return GNUNET_SYSERR;
1303     }
1304   /* Close the write end of the read pipe */
1305   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1306
1307   /* Close the read end of the write pipe */
1308   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1309
1310   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1311   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin, GNUNET_DISK_PIPE_END_WRITE);
1312
1313   plugin->server_read_task =
1314   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1315                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1316   return GNUNET_YES;
1317 }
1318
1319
1320
1321 /**
1322  * Entry point for the plugin.
1323  *
1324  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1325  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1326  */
1327 void *
1328 libgnunet_plugin_transport_wlan_init (void *cls)
1329 {
1330   struct GNUNET_SERVICE_Context *service;
1331   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1332   struct GNUNET_TRANSPORT_PluginFunctions *api;
1333   struct Plugin *plugin;
1334
1335   GNUNET_assert(cls !=NULL);
1336
1337   service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
1338         if (service == NULL){
1339                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1340                            _("Failed to start service for `%s' transport plugin.\n"),
1341                            "wlan");
1342                 return NULL;
1343         }
1344
1345   plugin = GNUNET_malloc (sizeof (struct Plugin));
1346   plugin->env = env;
1347   plugin->pendingsessions = 0;
1348   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1349   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1350
1351   wlan_transport_start_wlan_helper(plugin);
1352   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
1353
1354   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1355   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
1356
1357   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1358   api->cls = plugin;
1359   api->send = &wlan_plugin_send;
1360   api->disconnect = &wlan_plugin_disconnect;
1361   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1362   api->check_address = &wlan_plugin_address_suggested;
1363   api->address_to_string = &wlan_plugin_address_to_string;
1364
1365
1366   start_next_message_id();
1367
1368   return api;
1369 }
1370
1371
1372 /**
1373  * Exit point from the plugin.
1374  */
1375 //TODO doxigen
1376 void *
1377 libgnunet_plugin_transport_wlan_done (void *cls)
1378 {
1379   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1380   struct Plugin *plugin = api->cls;
1381
1382   GNUNET_assert(cls !=NULL);
1383
1384   GNUNET_free_non_null(plugin->mac_address);
1385   GNUNET_free (plugin);
1386   GNUNET_free (api);
1387   return NULL;
1388 }
1389
1390 /* end of plugin_transport_wlan.c */