kqueue.c revision 134236
1/*-
2 * Copyright (c) 2004 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/tools/regression/sockets/kqueue/kqueue.c 134236 2004-08-24 04:02:41Z rwatson $
27 */
28
29#include <sys/types.h>
30#include <sys/event.h>
31#include <sys/socket.h>
32#include <sys/time.h>
33
34#include <errno.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40
41/*-
42 * This test uses UNIX domain socket pairs to perform some basic exercising
43 * of kqueue functionality on sockets.  In particular, testing that for read
44 * and write filters, we see the correct detection of whether reads and
45 * writes should actually be able to occur.
46 *
47 * TODO:
48 * - Test read/write filters for listen/accept sockets.
49 * - Handle the XXXRW below regarding datagram sockets.
50 * - Test that watermark/buffer size "data" fields returned by kqueue are
51 *   correct.
52 * - Check that kqueue does something sensible when the remote endpoing is
53 *   closed.
54 */
55
56static void
57fail(int error, const char *func, const char *socktype, const char *rest)
58{
59
60	fprintf(stderr, "FAIL\n");
61
62	if (socktype == NULL)
63		fprintf(stderr, "%s(): %s\n", func, strerror(error));
64	else if (rest == NULL)
65		fprintf(stderr, "%s(%s): %s\n", func, socktype,
66		    strerror(error));
67	else
68		fprintf(stderr, "%s(%s, %s): %s\n", func, socktype, rest,
69		    strerror(error));
70	exit(-1);
71}
72
73static void
74fail_assertion(const char *func, const char *socktype, const char *rest,
75    const char *assertion)
76{
77
78	fprintf(stderr, "FAIL\n");
79
80	if (socktype == NULL)
81		fprintf(stderr, "%s(): assertion %s failed\n", func,
82		    assertion);
83	else if (rest == NULL)
84		fprintf(stderr, "%s(%s): assertion %s failed\n", func,
85		    socktype, assertion);
86	else
87		fprintf(stderr, "%s(%s, %s): assertion %s failed\n", func,
88		    socktype, rest, assertion);
89	exit(-1);
90}
91
92/*
93 * Test read kevent on a socket pair: check to make sure endpoint 0 isn't
94 * readable when we start, then write to endpoint 1 and confirm that endpoint
95 * 0 is now readable.  Drain the write, then check that it's not readable
96 * again.  Use non-blocking kqueue operations and socket operations.
97 */
98static void
99test_evfilt_read(int kq, int fd[2], const char *socktype)
100{
101	struct timespec ts;
102	struct kevent ke;
103	ssize_t len;
104	char ch;
105	int i;
106
107	EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
108	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
109		fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD");
110
111	/*
112	 * Confirm not readable to begin with, no I/O yet.
113	 */
114	ts.tv_sec = 0;
115	ts.tv_nsec = 0;
116	i = kevent(kq, NULL, 0, &ke, 1, &ts);
117	if (i == -1)
118		fail(errno, "kevent", socktype, "EVFILT_READ");
119	if (i != 0)
120		fail_assertion("kevent", socktype, "EVFILT_READ",
121		    "empty socket unreadable");
122
123	/*
124	 * Write a byte to one end.
125	 */
126	ch = 'a';
127	len = write(fd[1], &ch, sizeof(ch));
128	if (len == -1)
129		fail(errno, "write", socktype, NULL);
130	if (len != sizeof(ch))
131		fail_assertion("write", socktype, NULL, "write length");
132
133	/*
134	 * Other end should now be readable.
135	 */
136	ts.tv_sec = 0;
137	ts.tv_nsec = 0;
138	i = kevent(kq, NULL, 0, &ke, 1, &ts);
139	if (i == -1)
140		fail(errno, "kevent", socktype, "EVFILT_READ");
141	if (i != 1)
142		fail_assertion("kevent", socktype, "EVFILT_READ",
143		    "non-empty socket unreadable");
144
145	/*
146	 * Read a byte to clear the readable state.
147	 */
148	len = read(fd[0], &ch, sizeof(ch));
149	if (len == -1)
150		fail(errno, "read", socktype, NULL);
151	if (len != sizeof(ch))
152		fail_assertion("read", socktype, NULL, "read length");
153
154	/*
155	 * Now re-check for readability.
156	 */
157	ts.tv_sec = 0;
158	ts.tv_nsec = 0;
159	i = kevent(kq, NULL, 0, &ke, 1, &ts);
160	if (i == -1)
161		fail(errno, "kevent", socktype, "EVFILT_READ");
162	if (i != 0)
163		fail_assertion("kevent", socktype, "EVFILT_READ",
164		    "empty socket unreadable");
165
166	EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL);
167	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
168		fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE");
169}
170
171static void
172test_evfilt_write(int kq, int fd[2], const char *socktype)
173{
174	struct timespec ts;
175	struct kevent ke;
176	ssize_t len;
177	char ch;
178	int i;
179
180	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL);
181	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
182		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD");
183
184	/*
185	 * Confirm writable to begin with, no I/O yet.
186	 */
187	ts.tv_sec = 0;
188	ts.tv_nsec = 0;
189	i = kevent(kq, NULL, 0, &ke, 1, &ts);
190	if (i == -1)
191		fail(errno, "kevent", socktype, "EVFILT_WRITE");
192	if (i != 1)
193		fail_assertion("kevent", socktype, "EVFILT_WRITE",
194		    "empty socket unwritable");
195
196	/*
197	 * Write bytes into the socket until we can't write anymore.
198	 */
199	ch = 'a';
200	while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {};
201	if (len == -1 && errno != EAGAIN && errno != ENOBUFS)
202		fail(errno, "write", socktype, NULL);
203	if (len != -1 && len != sizeof(ch))
204		fail_assertion("write", socktype, NULL, "write length");
205
206	/*
207	 * Check to make sure the socket is no longer writable.
208	 */
209	ts.tv_sec = 0;
210	ts.tv_nsec = 0;
211	i = kevent(kq, NULL, 0, &ke, 1, &ts);
212	if (i == -1)
213		fail(errno, "kevent", socktype, "EVFILT_WRITE");
214	if (i != 0)
215		fail_assertion("kevent", socktype, "EVFILT_WRITE",
216		    "full socket writable");
217
218	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
219	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
220		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE");
221}
222
223/*
224 * Basic registration exercise for kqueue(2).  Create several types/brands of
225 * sockets, and confirm that we can register for various events on them.
226 */
227int
228main(int argc, char *argv[])
229{
230	int i, kq, sv[2];
231
232	kq = kqueue();
233	if (kq == -1)
234		fail(errno, "kqueue", NULL, NULL);
235
236	/*
237	 * Create a UNIX domain datagram socket, and attach/test/detach a
238	 * read filter on it.
239	 */
240	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
241		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
242
243	i = O_NONBLOCK;
244	if (fcntl(sv[0], F_SETFL, &i) != 0)
245		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
246	if (fcntl(sv[1], F_SETFL, &i) != 0)
247		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
248
249	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM");
250
251	if (close(sv[0]) == -1)
252		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
253	if (close(sv[1]) == -1)
254		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
255
256#if 0
257	/*
258	 * XXXRW: We disable the write test in the case of datagram sockets,
259	 * as kqueue can't tell when the remote socket receive buffer is
260	 * full, whereas the UNIX domain socket implementation can tell and
261	 * returns ENOBUFS.
262	 */
263	/*
264	 * Create a UNIX domain datagram socket, and attach/test/detach a
265	 * write filter on it.
266	 */
267	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
268		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
269
270	i = O_NONBLOCK;
271	if (fcntl(sv[0], F_SETFL, &i) != 0)
272		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
273	if (fcntl(sv[1], F_SETFL, &i) != 0)
274		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
275
276	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM");
277
278	if (close(sv[0]) == -1)
279		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
280	if (close(sv[1]) == -1)
281		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
282#endif
283
284	/*
285	 * Create a UNIX domain stream socket, and attach/test/detach a
286	 * read filter on it.
287	 */
288	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
289		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
290
291	i = O_NONBLOCK;
292	if (fcntl(sv[0], F_SETFL, &i) != 0)
293		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
294	if (fcntl(sv[1], F_SETFL, &i) != 0)
295		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
296
297	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM");
298
299	if (close(sv[0]) == -1)
300		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
301	if (close(sv[1]) == -1)
302		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
303
304	/*
305	 * Create a UNIX domain stream socket, and attach/test/detach a
306	 * write filter on it.
307	 */
308	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
309		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
310
311	i = O_NONBLOCK;
312	if (fcntl(sv[0], F_SETFL, &i) != 0)
313		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
314	if (fcntl(sv[1], F_SETFL, &i) != 0)
315		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
316
317	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM");
318
319	if (close(sv[0]) == -1)
320		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
321	if (close(sv[1]) == -1)
322		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
323
324	if (close(kq) == -1)
325		fail(errno, "close", "kq", NULL);
326
327	printf("PASS\n");
328	return (0);
329}
330