init to zero
[oweals/gnunet.git] / src / transport / test_plugin_transport_wlan_dummy.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010 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  * @file transport/test_transport_wlan_dummy.c
22  * @brief helper for the testcases for plugin_transport_wlan.c
23  * @author David Brodski
24  */
25
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <sys/time.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include <errno.h>
36 #include <resolv.h>
37 #include <string.h>
38 #include <utime.h>
39 #include <unistd.h>
40 #include <getopt.h>
41
42 #include "platform.h"
43 #include "gnunet_constants.h"
44 #include "gnunet_os_lib.h"
45 #include "gnunet_transport_plugin.h"
46 #include "transport.h"
47 #include "gnunet_util_lib.h"
48 #include "plugin_transport_wlan.h"
49 #include "gnunet_common.h"
50 #include "gnunet-transport-wlan-helper.h"
51 #include "gnunet_crypto_lib.h"
52 #include "wlan/loopback_helper.h"
53 #include "wlan/helper_common.h"
54
55 static int first;
56
57 static void
58 sigfunc(int sig)
59 {
60   closeprog = 1;
61   unlink(FIFO_FILE1);
62   unlink(FIFO_FILE2);
63 }
64
65 static void
66 stdin_send(void *cls, void *client, 
67            const struct GNUNET_MessageHeader *hdr)
68 {
69   struct sendbuf *write_pout = cls;
70   int sendsize;
71   struct GNUNET_MessageHeader newheader;
72   char * to_data;
73   char * to_radiotap;
74   char * to_start;
75
76   sendsize = ntohs(hdr->size) - sizeof(struct Radiotap_Send)
77       + sizeof(struct Radiotap_rx);
78
79   if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type))
80     {
81       fprintf(stderr, "Function stdin_send: wrong packet type\n");
82       exit(1);
83     }
84   if ((sendsize + write_pout->size) > MAXLINE * 2)
85     {
86       fprintf(stderr, "Function stdin_send: Packet too big for buffer\n");
87       exit(1);
88     }
89
90   newheader.size = htons(sendsize);
91   newheader.type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
92
93   to_start = write_pout->buf + write_pout->size;
94   memcpy(to_start, &newheader, sizeof(struct GNUNET_MessageHeader));
95   write_pout->size += sizeof(struct GNUNET_MessageHeader);
96
97   to_radiotap = to_start + sizeof(struct GNUNET_MessageHeader);
98   memset(to_radiotap, 0, sizeof (struct Radiotap_rx));
99   write_pout->size += sizeof(struct Radiotap_rx);
100
101   to_data = to_radiotap + sizeof(struct Radiotap_rx);
102   memcpy(to_data, 
103          ((char *) hdr) + sizeof(struct Radiotap_Send) + sizeof(struct GNUNET_MessageHeader),
104          ntohs(hdr->size) - sizeof(struct Radiotap_Send) - sizeof(struct GNUNET_MessageHeader));
105   write_pout->size += ntohs(hdr->size) - sizeof(struct Radiotap_Send) - sizeof(struct GNUNET_MessageHeader);
106 }
107
108 static void
109 file_in_send(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
110 {
111   struct sendbuf * write_std = cls;
112   uint16_t sendsize;
113
114   sendsize = ntohs(hdr->size);
115
116   if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type))
117     {
118       fprintf(stderr, "Function file_in_send: wrong packet type\n");
119       exit(1);
120     }
121   if ((sendsize + write_std->size) > MAXLINE * 2)
122     {
123       fprintf(stderr, "Function file_in_send: Packet too big for buffer\n");
124       exit(1);
125     }
126
127   memcpy(write_std->buf + write_std->size, hdr, sendsize);
128   write_std->size += sendsize;
129 }
130
131 int closeprog;
132
133
134 int
135 testmode(int argc, char *argv[])
136 {
137   struct stat st;
138   int erg;
139
140   FILE *fpin = NULL;
141   FILE *fpout = NULL;
142
143   int fdpin;
144   int fdpout;
145
146   //make the fifos if needed
147   if (0 != stat(FIFO_FILE1, &st))
148     {
149       if (0 == stat(FIFO_FILE2, &st))
150         {
151           fprintf(stderr, "FIFO_FILE2 exists, but FIFO_FILE1 not\n");
152           exit(1);
153         }
154
155       umask(0);
156       //unlink(FIFO_FILE1);
157       //unlink(FIFO_FILE2);
158       // FIXME: use mkfifo!
159      erg = mknod(FIFO_FILE1, S_IFIFO | 0666, 0);
160       if (0 != erg)
161         {
162           fprintf(stderr, "Error at mknode1 \n");
163           //exit(1);
164         }
165       erg = mknod(FIFO_FILE2, S_IFIFO | 0666, 0);
166       if (0 != erg)
167         {
168           fprintf(stderr, "Error at mknode2 \n");
169           //exit(1);
170         }
171
172     }
173   else
174     {
175
176       if (0 != stat(FIFO_FILE2, &st))
177         {
178           fprintf(stderr, "FIFO_FILE1 exists, but FIFO_FILE2 not\n");
179           exit(1);
180         }
181
182     }
183
184   if (strstr(argv[1], "1"))
185     {
186       //fprintf(stderr, "First\n");
187       first = 1;
188       fpin = fopen(FIFO_FILE1, "r");
189       if (NULL == fpin)
190         {
191           fprintf(stderr, "fopen of read FIFO_FILE1\n");
192           goto end;
193         }
194       fpout = fopen(FIFO_FILE2, "w");
195       if (NULL == fpout)
196         {
197           fprintf(stderr, "fopen of write FIFO_FILE2\n");
198           goto end;
199         }
200
201     }
202   else
203     {
204       first = 0;
205       //fprintf(stderr, "Second\n");
206       fpout = fopen(FIFO_FILE1, "w");
207       if (NULL == fpout)
208         {
209           fprintf(stderr, "fopen of write FIFO_FILE1\n");
210           goto end;
211         }
212       fpin = fopen(FIFO_FILE2, "r");
213       if (NULL == fpin)
214         {
215           fprintf(stderr, "fopen of read FIFO_FILE2\n");
216           goto end;
217         }
218
219     }
220
221   fdpin = fileno(fpin);
222   GNUNET_assert(fpin >= 0);
223
224   if (fdpin >= FD_SETSIZE)
225     {
226       fprintf(stderr, "File fdpin number too large (%d > %u)\n", fdpin,
227           (unsigned int) FD_SETSIZE);
228       goto end;
229     }
230
231   fdpout = fileno(fpout);
232   GNUNET_assert(fdpout >= 0 );
233
234   if (fdpout >= FD_SETSIZE)
235     {
236       fprintf(stderr, "File fdpout number too large (%d > %u)\n", fdpout,
237           (unsigned int) FD_SETSIZE);
238       goto end;
239
240     }
241
242   signal(SIGINT, &sigfunc);
243   signal(SIGTERM, &sigfunc);
244
245   char readbuf[MAXLINE];
246   int readsize = 0;
247   struct sendbuf write_std;
248   write_std.size = 0;
249   write_std.pos = 0;
250
251   struct sendbuf write_pout;
252   write_pout.size = 0;
253   write_pout.pos = 0;
254
255   int ret = 0;
256   int maxfd = 0;
257
258   fd_set rfds;
259   fd_set wfds;
260   struct timeval tv;
261   int retval;
262
263   struct GNUNET_SERVER_MessageStreamTokenizer * stdin_mst;
264   struct GNUNET_SERVER_MessageStreamTokenizer * file_in_mst;
265
266   stdin_mst = GNUNET_SERVER_mst_create(&stdin_send, &write_pout);
267   file_in_mst = GNUNET_SERVER_mst_create(&file_in_send, &write_std);
268
269   //send mac first
270
271   struct MacAddress macaddr;
272
273   //Send random mac address
274   macaddr.mac[0] = 0x13;
275   macaddr.mac[1] = 0x22;
276   macaddr.mac[2] = 0x33;
277   macaddr.mac[3] = 0x44;
278   macaddr.mac[4] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 256);
279   macaddr.mac[5] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, 256);
280
281   write_std.size = send_mac_to_plugin(write_std.buf, macaddr.mac);
282
283   while (0 == closeprog)
284     {
285
286       maxfd = 0;
287
288       //set timeout
289       tv.tv_sec = 5;
290       tv.tv_usec = 0;
291
292       FD_ZERO(&rfds);
293       // if output queue is empty
294       if (0 == write_pout.size)
295         {
296           FD_SET(STDIN_FILENO, &rfds);
297
298         }
299       if (0 == write_std.size)
300         {
301           FD_SET(fdpin, &rfds);
302           maxfd = fdpin;
303         }
304       FD_ZERO(&wfds);
305       // if there is something to write
306       if (0 < write_std.size)
307         {
308           FD_SET(STDOUT_FILENO, &wfds);
309           maxfd = MAX(maxfd, STDOUT_FILENO);
310         }
311
312       if (0 < write_pout.size)
313         {
314           FD_SET(fdpout, &wfds);
315           maxfd = MAX(maxfd, fdpout);
316         }
317
318       retval = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
319
320       if (-1 == retval && EINTR == errno)
321         {
322           continue;
323         }
324       if (0 > retval)
325         {
326           fprintf(stderr, "select failed: %s\n", strerror(errno));
327           closeprog = 1;
328           break;
329         }
330
331       if (FD_ISSET(STDOUT_FILENO, &wfds))
332         {
333           ret = write(STDOUT_FILENO, 
334                       write_std.buf + write_std.pos,
335                       write_std.size - write_std.pos);
336           if (0 > ret)
337             {
338               closeprog = 1;
339               fprintf(stderr, "Write ERROR to STDOUT\n");
340               break;
341             }
342           else
343             {
344               write_std.pos += ret;
345               // check if finished
346               if (write_std.pos == write_std.size)
347                 {
348                   write_std.pos = 0;
349                   write_std.size = 0;
350                 }
351             }
352         }
353
354       if (FD_ISSET(fdpout, &wfds))
355         {
356           ret = write(fdpout,
357                       write_pout.buf + write_pout.pos, 
358                       write_pout.size - write_pout.pos);
359           
360           if (0 > ret)
361             {
362               closeprog = 1;
363               fprintf(stderr, "Write ERROR to fdpout\n");
364             }
365           else
366             {
367               write_pout.pos += ret;
368               // check if finished
369               if (write_pout.pos == write_pout.size)
370                 {
371                   write_pout.pos = 0;
372                   write_pout.size = 0;
373                 }
374             }
375         }
376
377       if (FD_ISSET(STDIN_FILENO, &rfds))
378         {
379           readsize = read(STDIN_FILENO, readbuf, sizeof(readbuf));
380
381           if (0 > readsize)
382             {
383               closeprog = 1;
384               fprintf(stderr, "Read ERROR to STDIN_FILENO\n");
385             }
386           else if (0 < readsize)
387             {
388               GNUNET_SERVER_mst_receive(stdin_mst, NULL, readbuf, readsize,
389                   GNUNET_NO, GNUNET_NO);
390
391             }
392           else
393             {
394               //eof
395               closeprog = 1;
396             }
397         }
398
399       if (FD_ISSET(fdpin, &rfds))
400         {
401           readsize = read(fdpin, readbuf, sizeof(readbuf));
402
403           if (0 > readsize)
404             {
405               closeprog = 1;
406               fprintf(stderr, "Read ERROR to fdpin: %s\n", strerror(errno));
407               break;
408             }
409           else if (0 < readsize)
410             {
411               GNUNET_SERVER_mst_receive(file_in_mst, NULL, readbuf, readsize,
412                   GNUNET_NO, GNUNET_NO);
413
414             }
415           else
416             {
417               //eof
418               closeprog = 1;
419             }
420         }
421
422     }
423
424   //clean up
425
426   GNUNET_SERVER_mst_destroy(stdin_mst);
427   GNUNET_SERVER_mst_destroy(file_in_mst);
428
429   end: if (fpout != NULL)
430     fclose(fpout);
431   if (fpin != NULL)
432     fclose(fpin);
433
434   if (1 == first)
435     {
436       unlink(FIFO_FILE1);
437       unlink(FIFO_FILE2);
438     }
439
440   return (0);
441 }
442
443 int
444 main(int argc, char *argv[])
445 {
446   if (2 != argc)
447     {
448       fprintf (stderr,
449                "This program must be started with the operating mode as argument.\n");
450       fprintf (stderr,
451                "Usage: options\n"
452                "options:\n"
453                "1 = first loopback file\n"
454                "2 = second loopback file\n"
455                "\n");
456       return 1;
457     }
458   if (strstr(argv[1], "1") || strstr(argv[1], "2"))
459     return testmode(argc, argv);
460   return 1;
461 }