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