2 * Copyright 2000, International Business Machines Corporation and others.
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
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
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
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
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.
41 #include <sys/select.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
46 #include <netinet/in.h>
49 #include <sys/ioctl.h>
53 #include <afsconfig.h>
54 #include <afs/param.h>
62 /* Put this in lwp.h? */
63 extern int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
66 void sendTest(int, int, int, int);
80 printf("Usage: selclient [-fd n] [-oob] [-soob] [-delay n] [-end] [-write n] host port\n");
81 printf("\t-fd n\tUse file descriptor n for socket.\n");
82 printf("\t-oob\tRequest a MSG_OOB from server.\n");
83 printf("\t-soob\tSend a MSG_OOB to server.\n");
84 printf("\t-delay n\tAsk server to delay n seconds for my writes.\n");
85 printf("\t-end\tAsk server to terminate.\n");
86 printf("\t-write\tWrite n bytes to server, verify reply.\n");
90 main(int ac, char **av)
95 struct hostent *hostent;
96 int host; /* net order. */
97 short port = -1; /* host order. */
100 struct sockaddr_in saddr;
110 signal(SIGIO, sigIO);
113 for (i=1; i<ac; i++) {
114 if (!strcmp("-fd", av[i])) {
116 printf("Missing number for -fd option.\n");
121 printf("%s: %d: file descriptor must be at least 3.\n",
126 else if (!strcmp("-end", av[i])) {
129 else if (!strcmp("-delay", av[i])) {
131 printf("%s: Missing time for -delay option.\n", program);
136 printf("%s: %s: delay must be at least 0 seconds.\n",
141 else if (!strcmp("-write", av[i])) {
144 printf("%s: Missing size for -write option.\n", program);
147 writeSize = atoi(av[i]);
149 printf("%s: %s: Write size must be at least 1 byte.\n",
154 else if (!strcmp("-oob", av[i])) {
157 else if (!strcmp("-soob", av[i])) {
164 else if (port == -1) {
167 printf("%s: %s: port must be at least 1\n",
173 printf("%s: %s: Unknown argument.\n", program, av[i]);
179 printf("%s: Missing hostname and port.\n", program);
183 printf("%s: Missing port.\n", program);
189 printf("%s: Using default socket of %d.\n", program, setFD);
192 if (!(hostent = gethostbyname(hostname))) {
193 printf("%s: Failed to find host entry for %s.\n",
198 memcpy((void*)&host, (const void*)hostent->h_addr, sizeof(host));
202 /* Connect to server. */
203 sockFD = socket(AF_INET, SOCK_STREAM, 0);
207 printf("%s: Using socket at file descriptor %d.\n", program, sockFD);
209 memset((void*)&saddr, 0, sizeof(saddr));
210 saddr.sin_family = AF_INET;
211 saddr.sin_addr.s_addr = host; /* already in network byte order. */
212 saddr.sin_port = htons(port);
214 if (connect(sockFD, (struct sockaddr*)&saddr, sizeof(saddr))<0) {
223 Log("Will send OOB in 2 seconds.\n");
226 Log("Sent OOB, sleeping for 5 seconds.\n");
228 Log("Sent OOB, exiting.\n");
232 sendTest(sockFD, delay, reqOOB, writeSize);
241 sendTest(int sockFD, int delay, int reqOOB, int size)
244 fd_set *rfds, *wfds, *efds;
250 buf = (char*)malloc(size);
252 bufTest = (char*)malloc(size);
255 for (j=i=0; i<size; i++, j++) {
256 if (j==END_DATA) j++;
261 selCmd.sc_cmd = SC_WRITE;
262 selCmd.sc_info = size;
263 selCmd.sc_delay = delay;
264 selCmd.sc_flags = SC_WAIT_ONLY;
266 nbytes = write(sockFD, (char*)&selCmd, sizeof(selCmd));
267 assert(nbytes == sizeof(selCmd));
269 Log("Starting to write %d bytes.\n", size);
271 nbytes = write(sockFD, buf, size);
272 assert(nbytes == size);
275 rfds = IOMGR_AllocFDSet();
276 wfds = IOMGR_AllocFDSet();
277 efds = IOMGR_AllocFDSet();
278 if (!rfds || !wfds || !efds) {
279 printf("%s: Could not allocate all fd_sets.\n", program);
283 for (writeIndex = i=0; i<size; writeIndex++, i++) {
284 FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds);
285 FD_SET(sockFD, wfds);
286 FD_SET(sockFD, efds);
288 code = IOMGR_Select(sockFD+1, rfds, wfds, efds,
289 (struct timeval*)NULL);
292 if (FD_ISSET(sockFD, wfds)) {
294 if (etime - stime > 1 ) {
295 Log("Waited %d seconds to write at offset %d.\n",
299 nbytes = write(sockFD, &buf[i], 1);
301 if (etime - stime > 1 ) {
302 Log("Waited %d seconds IN write.\n", etime - stime);
305 FD_CLR(sockFD, wfds);
307 assertNullFDSet(0, rfds);
308 assertNullFDSet(0, wfds);
309 assertNullFDSet(0, efds);
313 Log("Wrote %d bytes.\n", size);
316 nbytes = read(sockFD, &bufTest[i], size);
319 Log("Read %d bytes.\n", size);
321 assert(memcmp(buf, bufTest, size) == 0);
322 Log("Compared %d bytes.\n", size);
331 if (write(fd, (char*)&sc, sizeof(sc)) != sizeof(sc)) {
332 Die(1, "(sendEnd) write failed: ");