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