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