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.
37 #include <afsconfig.h>
38 #include <afs/param.h>
45 #include <sys/select.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
50 #include <netinet/in.h>
53 #include <sys/ioctl.h>
61 /* Put this in lwp.h? */
62 extern int IOMGR_Select(int, fd_set
*, fd_set
*, fd_set
*, struct timeval
*);
65 void sendTest(int, int, int, int);
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");
91 main(int ac
, char **av
)
96 struct hostent
*hostent
;
97 int host
; /* net order. */
98 short port
= -1; /* host order. */
101 struct sockaddr_in saddr
;
111 signal(SIGIO
, sigIO
);
114 for (i
= 1; i
< ac
; i
++) {
115 if (!strcmp("-fd", av
[i
])) {
117 printf("Missing number for -fd option.\n");
122 printf("%s: %d: file descriptor must be at least 3.\n",
126 } else if (!strcmp("-end", av
[i
])) {
128 } else if (!strcmp("-delay", av
[i
])) {
130 printf("%s: Missing time for -delay option.\n", program
);
135 printf("%s: %s: delay must be at least 0 seconds.\n", program
,
139 } else if (!strcmp("-write", av
[i
])) {
142 printf("%s: Missing size for -write option.\n", program
);
145 writeSize
= atoi(av
[i
]);
147 printf("%s: %s: Write size must be at least 1 byte.\n",
151 } else if (!strcmp("-oob", av
[i
])) {
153 } else if (!strcmp("-soob", av
[i
])) {
158 } else if (port
== -1) {
161 printf("%s: %s: port must be at least 1\n", program
,
166 printf("%s: %s: Unknown argument.\n", program
, av
[i
]);
172 printf("%s: Missing hostname and port.\n", program
);
176 printf("%s: Missing port.\n", program
);
180 if (writeSize
== 0 && doEnd
== 0 && putOOB
== 0) {
181 printf("%s: Missing action.\n", program
);
187 printf("%s: Using default socket of %d.\n", program
, setFD
);
190 if (!(hostent
= gethostbyname(hostname
))) {
191 printf("%s: Failed to find host entry for %s.\n", program
, hostname
);
195 memcpy((void *)&host
, (const void *)hostent
->h_addr
, sizeof(host
));
199 /* Connect to server. */
200 sockFD
= socket(AF_INET
, SOCK_STREAM
, 0);
204 printf("%s: Using socket at file descriptor %d.\n", program
, sockFD
);
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
);
211 if (connect(sockFD
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0) {
219 Log("Will send OOB in 2 seconds.\n");
222 Log("Sent OOB, sleeping for 5 seconds.\n");
224 Log("Sent OOB, exiting.\n");
227 sendTest(sockFD
, delay
, reqOOB
, writeSize
);
236 sendTest(int sockFD
, int delay
, int reqOOB
, int size
)
239 fd_set
*rfds
, *wfds
, *efds
;
247 bufTest
= malloc(size
);
250 for (j
= i
= 0; i
< size
; i
++, j
++) {
258 selCmd
.sc_cmd
= SC_WRITE
;
259 selCmd
.sc_info
= size
;
260 selCmd
.sc_delay
= delay
;
261 selCmd
.sc_flags
= SC_WAIT_ONLY
;
263 nbytes
= write(sockFD
, (char *)&selCmd
, sizeof(selCmd
));
264 assert(nbytes
== sizeof(selCmd
));
266 Log("Starting to write %d bytes.\n", size
);
268 nbytes
= write(sockFD
, buf
, size
);
269 assert(nbytes
== size
);
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
);
279 for (writeIndex
= i
= 0; i
< size
; writeIndex
++, i
++) {
283 FD_SET(sockFD
, wfds
);
284 FD_SET(sockFD
, efds
);
287 IOMGR_Select(sockFD
+ 1, rfds
, wfds
, efds
,
291 if (FD_ISSET(sockFD
, wfds
)) {
293 if (etime
- stime
> 1) {
294 Log("Waited %d seconds to write at offset %d.\n",
298 nbytes
= write(sockFD
, &buf
[i
], 1);
300 if (etime
- stime
> 1) {
301 Log("Waited %d seconds IN write.\n", etime
- stime
);
304 FD_CLR(sockFD
, wfds
);
306 assertNullFDSet(0, rfds
);
307 assertNullFDSet(0, wfds
);
308 assertNullFDSet(0, efds
);
312 Log("Wrote %d bytes.\n", size
);
315 nbytes
= read(sockFD
, &bufTest
[i
], size
);
318 Log("Read %d bytes.\n", size
);
320 assert(memcmp(buf
, bufTest
, size
) == 0);
321 Log("Compared %d bytes.\n", size
);
331 if (write(fd
, (char *)&sc
, sizeof(sc
)) != sizeof(sc
)) {
332 Die(1, "(sendEnd) write failed: ");