venus: Remove dedebug
[openafs.git] / src / lwp / test / selclient.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* selclient.c tests the IOMGR_Select interface. Specifically it verifies
11  * that the read/write/exception lists work correctly with file descriptors
12  * larger than 31. Generally, the calls to IOMGR_Select pass in all the
13  * read, write and exception fd_sets. When handling is complete, the file
14  * descriptor is cleared from the set. Then if fd_set is checked to make sure
15  * there are no other bits set. The fd_sets which should have had nothing set
16  * are also checked.
17  * 
18  * The client can send one of the following:
19  * -end - shoots the selserver.
20  * -delay n - The selserver thread handling this request should sleep for
21  *            n seconds before accepting data. Used in conjuction with -write
22  *            so that the write STREAM can fill. This tests the IOMGR_Select
23  *            write fd_sets.
24  * -write n - writes n bytes to the selserver. If -delay is not set, a default
25  *            of 5 seconds is used.
26  * -soob - Send an out-of-band message to selserver. Tests the exception
27  *            fd_set.
28  */
29
30 /* Typical test scanario:
31  * selclient -soob : used to test exception fd's on selserver.
32  * selclient -delay 20 -write 150000 : used to test read/write fd's.
33  * Adjust delay to 40 seconds if running loopback. Times and sizes derived
34  * on IRIX 6.2 and 6.4.
35  */
36
37 #include <afsconfig.h>
38 #include <afs/param.h>
39
40
41 #include <unistd.h>
42 #include <stdio.h>
43 #include <stdarg.h>
44 #include <errno.h>
45 #include <sys/select.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <string.h>
49 #include <sys/time.h>
50 #include <netinet/in.h>
51 #include <netdb.h>
52 #include <signal.h>
53 #include <sys/ioctl.h>
54 #include <assert.h>
55 #include <time.h>
56
57
58 #include "lwp.h"
59 #include "seltest.h"
60
61 /* Put this in lwp.h? */
62 extern int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
63
64
65 void sendTest(int, int, int, int);
66 void sendEnd(int);
67
68 int nSigIO = 0;
69 void
70 sigIO()
71 {
72     nSigIO++;
73 }
74
75 char *program;
76
77
78 Usage()
79 {
80     printf
81         ("Usage: selclient [-fd n] [-oob] [-soob] [-delay n] [-end] [-write n] host port\n");
82     printf("\t-fd n\tUse file descriptor n for socket.\n");
83     printf("\t-oob\tRequest a MSG_OOB from server.\n");
84     printf("\t-soob\tSend a MSG_OOB to server.\n");
85     printf("\t-delay n\tAsk server to delay n seconds for my writes.\n");
86     printf("\t-end\tAsk server to terminate.\n");
87     printf("\t-write\tWrite n bytes to server, verify reply.\n");
88     exit(1);
89 }
90
91 main(int ac, char **av)
92 {
93     int i;
94     int on = 1;
95     char *hostname = 0;
96     struct hostent *hostent;
97     int host;                   /* net order. */
98     short port = -1;            /* host order. */
99     int setFD = 0;
100     int sockFD;
101     struct sockaddr_in saddr;
102     int reqOOB = 0;
103     int putOOB = 0;
104     int delay = 5;
105     int doEnd = 0;
106     int doWrite = 0;
107     int writeSize = 0;
108
109     program = av[0];
110
111     signal(SIGIO, sigIO);
112
113
114     for (i = 1; i < ac; i++) {
115         if (!strcmp("-fd", av[i])) {
116             if (++i >= ac) {
117                 printf("Missing number for -fd option.\n");
118                 Usage();
119             }
120             setFD = atoi(av[i]);
121             if (setFD <= 2) {
122                 printf("%s: %d: file descriptor must be at least 3.\n",
123                        program, setFD);
124                 Usage();
125             }
126         } else if (!strcmp("-end", av[i])) {
127             doEnd = 1;
128         } else if (!strcmp("-delay", av[i])) {
129             if (++i >= ac) {
130                 printf("%s: Missing time for -delay option.\n", program);
131                 Usage();
132             }
133             delay = atoi(av[i]);
134             if (delay < 0) {
135                 printf("%s: %s: delay must be at least 0 seconds.\n", program,
136                        av[i]);
137                 Usage();
138             }
139         } else if (!strcmp("-write", av[i])) {
140             doWrite = 1;
141             if (++i >= ac) {
142                 printf("%s: Missing size for -write option.\n", program);
143                 Usage();
144             }
145             writeSize = atoi(av[i]);
146             if (writeSize < 1) {
147                 printf("%s: %s: Write size must be at least 1 byte.\n",
148                        program, av[i]);
149                 Usage();
150             }
151         } else if (!strcmp("-oob", av[i])) {
152             reqOOB = 1;
153         } else if (!strcmp("-soob", av[i])) {
154             putOOB = 1;
155         } else {
156             if (!hostname) {
157                 hostname = av[i];
158             } else if (port == -1) {
159                 port = atoi(av[i]);
160                 if (port <= 0) {
161                     printf("%s: %s: port must be at least 1\n", program,
162                            av[i]);
163                     Usage();
164                 }
165             } else {
166                 printf("%s: %s: Unknown argument.\n", program, av[i]);
167             }
168         }
169     }
170
171     if (!hostname) {
172         printf("%s: Missing hostname and port.\n", program);
173         Usage();
174     }
175     if (port == -1) {
176         printf("%s: Missing port.\n", program);
177         Usage();
178     }
179
180     if (writeSize == 0 && doEnd == 0 && putOOB == 0) {
181         printf("%s: Missing action.\n", program);
182         Usage();
183     }
184
185     if (!setFD) {
186         setFD = 31;
187         printf("%s: Using default socket of %d.\n", program, setFD);
188     }
189
190     if (!(hostent = gethostbyname(hostname))) {
191         printf("%s: Failed to find host entry for %s.\n", program, hostname);
192         exit(1);
193     }
194
195     memcpy((void *)&host, (const void *)hostent->h_addr, sizeof(host));
196
197     OpenFDs(setFD);
198
199     /* Connect to server. */
200     sockFD = socket(AF_INET, SOCK_STREAM, 0);
201     if (sockFD < 0) {
202         Die(0, "socket");
203     }
204     printf("%s: Using socket at file descriptor %d.\n", program, sockFD);
205
206     memset((void *)&saddr, 0, sizeof(saddr));
207     saddr.sin_family = AF_INET;
208     saddr.sin_addr.s_addr = host;       /* already in network byte order. */
209     saddr.sin_port = htons(port);
210
211     if (connect(sockFD, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
212         assert(0);
213     }
214
215
216     if (doEnd) {
217         sendEnd(sockFD);
218     } else if (putOOB) {
219         Log("Will send OOB in 2 seconds.\n");
220         sleep(2);
221         sendOOB(sockFD);
222         Log("Sent OOB, sleeping for 5 seconds.\n");
223         sleep(5);
224         Log("Sent OOB, exiting.\n");
225     } else {
226         IOMGR_Initialize();
227         sendTest(sockFD, delay, reqOOB, writeSize);
228     }
229     close(sockFD);
230 }
231
232 /* sendTest
233  */
234 int writeIndex;
235 void
236 sendTest(int sockFD, int delay, int reqOOB, int size)
237 {
238     char *buf, *bufTest;
239     fd_set *rfds, *wfds, *efds;
240     int i, j;
241     int nbytes, code;
242     selcmd_t selCmd;
243     time_t stime, etime;
244
245     buf = malloc(size);
246     assert(buf);
247     bufTest = malloc(size);
248     assert(bufTest);
249
250     for (j = i = 0; i < size; i++, j++) {
251         if (j == END_DATA)
252             j++;
253         if (j > 255)
254             j = 0;
255         buf[i] = (char)j;
256     }
257
258     selCmd.sc_cmd = SC_WRITE;
259     selCmd.sc_info = size;
260     selCmd.sc_delay = delay;
261     selCmd.sc_flags = SC_WAIT_ONLY;
262
263     nbytes = write(sockFD, (char *)&selCmd, sizeof(selCmd));
264     assert(nbytes == sizeof(selCmd));
265
266     Log("Starting to write %d bytes.\n", size);
267     if (!delay) {
268         nbytes = write(sockFD, buf, size);
269         assert(nbytes == size);
270     } else {
271         rfds = IOMGR_AllocFDSet();
272         wfds = IOMGR_AllocFDSet();
273         efds = IOMGR_AllocFDSet();
274         if (!rfds || !wfds || !efds) {
275             printf("%s: Could not allocate all fd_sets.\n", program);
276             exit(1);
277         }
278
279         for (writeIndex = i = 0; i < size; writeIndex++, i++) {
280             FD_ZERO(rfds);
281             FD_ZERO(wfds);
282             FD_ZERO(efds);
283             FD_SET(sockFD, wfds);
284             FD_SET(sockFD, efds);
285             (void)time(&stime);
286             code =
287                 IOMGR_Select(sockFD + 1, rfds, wfds, efds,
288                              NULL);
289             assert(code > 0);
290
291             if (FD_ISSET(sockFD, wfds)) {
292                 (void)time(&etime);
293                 if (etime - stime > 1) {
294                     Log("Waited %d seconds to write at offset %d.\n",
295                         etime - stime, i);
296                 }
297                 stime = etime;
298                 nbytes = write(sockFD, &buf[i], 1);
299                 (void)time(&etime);
300                 if (etime - stime > 1) {
301                     Log("Waited %d seconds IN write.\n", etime - stime);
302                 }
303                 assert(nbytes == 1);
304                 FD_CLR(sockFD, wfds);
305             }
306             assertNullFDSet(0, rfds);
307             assertNullFDSet(0, wfds);
308             assertNullFDSet(0, efds);
309         }
310     }
311
312     Log("Wrote %d bytes.\n", size);
313     i = 0;
314     while (i < size) {
315         nbytes = read(sockFD, &bufTest[i], size);
316         i += nbytes;
317     }
318     Log("Read %d bytes.\n", size);
319
320     assert(memcmp(buf, bufTest, size) == 0);
321     Log("Compared %d bytes.\n", size);
322 }
323
324 void
325 sendEnd(int fd)
326 {
327     selcmd_t sc;
328
329     sc.sc_cmd = SC_END;
330
331     if (write(fd, (char *)&sc, sizeof(sc)) != sizeof(sc)) {
332         Die(1, "(sendEnd) write failed: ");
333     }
334 }