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
27#include <sys/types.h>
28#include <sys/event.h>
29#include <sys/socket.h>
30#include <sys/time.h>
31
32#include <errno.h>
33#include <fcntl.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39static int	curtest = 1;
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
56#define OK(testname)	printf("ok %d - %s\n", curtest, testname); \
57			curtest++;
58
59static void
60fail(int error, const char *func, const char *socktype, const char *rest)
61{
62
63	printf("not ok %d\n", curtest);
64
65	if (socktype == NULL)
66		printf("# %s(): %s\n", func, strerror(error));
67	else if (rest == NULL)
68		printf("# %s(%s): %s\n", func, socktype,
69		    strerror(error));
70	else
71		printf("# %s(%s, %s): %s\n", func, socktype, rest,
72		    strerror(error));
73	exit(-1);
74}
75
76static void
77fail_assertion(const char *func, const char *socktype, const char *rest,
78    const char *assertion)
79{
80
81	printf("not ok %d - %s\n", curtest, assertion);
82
83	if (socktype == NULL)
84		printf("# %s(): assertion %s failed\n", func,
85		    assertion);
86	else if (rest == NULL)
87		printf("# %s(%s): assertion %s failed\n", func,
88		    socktype, assertion);
89	else
90		printf("# %s(%s, %s): assertion %s failed\n", func,
91		    socktype, rest, assertion);
92	exit(-1);
93}
94
95/*
96 * Test read kevent on a socket pair: check to make sure endpoint 0 isn't
97 * readable when we start, then write to endpoint 1 and confirm that endpoint
98 * 0 is now readable.  Drain the write, then check that it's not readable
99 * again.  Use non-blocking kqueue operations and socket operations.
100 */
101static void
102test_evfilt_read(int kq, int fd[2], const char *socktype)
103{
104	struct timespec ts;
105	struct kevent ke;
106	ssize_t len;
107	char ch;
108	int i;
109
110	EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
111	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
112		fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD");
113	OK("EVFILT_READ, EV_ADD");
114
115	/*
116	 * Confirm not readable to begin with, no I/O yet.
117	 */
118	ts.tv_sec = 0;
119	ts.tv_nsec = 0;
120	i = kevent(kq, NULL, 0, &ke, 1, &ts);
121	if (i == -1)
122		fail(errno, "kevent", socktype, "EVFILT_READ");
123	OK("EVFILT_READ");
124	if (i != 0)
125		fail_assertion("kevent", socktype, "EVFILT_READ",
126		    "empty socket unreadable");
127	OK("empty socket unreadable");
128
129	/*
130	 * Write a byte to one end.
131	 */
132	ch = 'a';
133	len = write(fd[1], &ch, sizeof(ch));
134	if (len == -1)
135		fail(errno, "write", socktype, NULL);
136	OK("write one byte");
137	if (len != sizeof(ch))
138		fail_assertion("write", socktype, NULL, "write length");
139	OK("write one byte length");
140
141	/*
142	 * Other end should now be readable.
143	 */
144	ts.tv_sec = 0;
145	ts.tv_nsec = 0;
146	i = kevent(kq, NULL, 0, &ke, 1, &ts);
147	if (i == -1)
148		fail(errno, "kevent", socktype, "EVFILT_READ");
149	OK("EVFILT_READ");
150	if (i != 1)
151		fail_assertion("kevent", socktype, "EVFILT_READ",
152		    "non-empty socket unreadable");
153	OK("non-empty socket unreadable");
154
155	/*
156	 * Read a byte to clear the readable state.
157	 */
158	len = read(fd[0], &ch, sizeof(ch));
159	if (len == -1)
160		fail(errno, "read", socktype, NULL);
161	OK("read one byte");
162	if (len != sizeof(ch))
163		fail_assertion("read", socktype, NULL, "read length");
164	OK("read one byte length");
165
166	/*
167	 * Now re-check for readability.
168	 */
169	ts.tv_sec = 0;
170	ts.tv_nsec = 0;
171	i = kevent(kq, NULL, 0, &ke, 1, &ts);
172	if (i == -1)
173		fail(errno, "kevent", socktype, "EVFILT_READ");
174	OK("EVFILT_READ");
175	if (i != 0)
176		fail_assertion("kevent", socktype, "EVFILT_READ",
177		    "empty socket unreadable");
178	OK("empty socket unreadable");
179
180	EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL);
181	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
182		fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE");
183	OK("EVFILT_READ, EV_DELETE");
184}
185
186static void
187test_evfilt_write(int kq, int fd[2], const char *socktype)
188{
189	struct timespec ts;
190	struct kevent ke;
191	ssize_t len;
192	char ch;
193	int i;
194
195	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL);
196	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
197		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD");
198	OK("EVFILE_WRITE, EV_ADD");
199
200	/*
201	 * Confirm writable to begin with, no I/O yet.
202	 */
203	ts.tv_sec = 0;
204	ts.tv_nsec = 0;
205	i = kevent(kq, NULL, 0, &ke, 1, &ts);
206	if (i == -1)
207		fail(errno, "kevent", socktype, "EVFILT_WRITE");
208	OK("EVFILE_WRITE");
209	if (i != 1)
210		fail_assertion("kevent", socktype, "EVFILT_WRITE",
211		    "empty socket unwritable");
212	OK("empty socket unwritable");
213
214	/*
215	 * Write bytes into the socket until we can't write anymore.
216	 */
217	ch = 'a';
218	while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {};
219	if (len == -1 && errno != EAGAIN && errno != ENOBUFS)
220		fail(errno, "write", socktype, NULL);
221	OK("write");
222	if (len != -1 && len != sizeof(ch))
223		fail_assertion("write", socktype, NULL, "write length");
224	OK("write length");
225
226	/*
227	 * Check to make sure the socket is no longer writable.
228	 */
229	ts.tv_sec = 0;
230	ts.tv_nsec = 0;
231	i = kevent(kq, NULL, 0, &ke, 1, &ts);
232	if (i == -1)
233		fail(errno, "kevent", socktype, "EVFILT_WRITE");
234	OK("EVFILT_WRITE");
235	if (i != 0)
236		fail_assertion("kevent", socktype, "EVFILT_WRITE",
237		    "full socket writable");
238	OK("full socket writable");
239
240	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
241	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
242		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE");
243	OK("EVFILT_WRITE, EV_DELETE");
244}
245
246/*
247 * Basic registration exercise for kqueue(2).  Create several types/brands of
248 * sockets, and confirm that we can register for various events on them.
249 */
250int
251main(void)
252{
253	int kq, sv[2];
254
255	printf("1..49\n");
256
257	kq = kqueue();
258	if (kq == -1)
259		fail(errno, "kqueue", NULL, NULL);
260	OK("kqueue()");
261
262	/*
263	 * Create a UNIX domain datagram socket, and attach/test/detach a
264	 * read filter on it.
265	 */
266	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
267		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
268	OK("socketpair() 1");
269
270	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
271		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
272	OK("fcntl() 1");
273	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
274		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
275	OK("fnctl() 2");
276
277	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM");
278
279	if (close(sv[0]) == -1)
280		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
281	OK("close() 1");
282	if (close(sv[1]) == -1)
283		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
284	OK("close() 2");
285
286#if 0
287	/*
288	 * XXXRW: We disable the write test in the case of datagram sockets,
289	 * as kqueue can't tell when the remote socket receive buffer is
290	 * full, whereas the UNIX domain socket implementation can tell and
291	 * returns ENOBUFS.
292	 */
293	/*
294	 * Create a UNIX domain datagram socket, and attach/test/detach a
295	 * write filter on it.
296	 */
297	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
298		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
299
300	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
301		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
302	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
303		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
304
305	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM");
306
307	if (close(sv[0]) == -1)
308		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
309	if (close(sv[1]) == -1)
310		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
311#endif
312
313	/*
314	 * Create a UNIX domain stream socket, and attach/test/detach a
315	 * read filter on it.
316	 */
317	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
318		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
319	OK("socketpair() 2");
320
321	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
322		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
323	OK("fcntl() 3");
324	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
325		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
326	OK("fcntl() 4");
327
328	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM");
329
330	if (close(sv[0]) == -1)
331		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
332	OK("close() 3");
333	if (close(sv[1]) == -1)
334		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
335	OK("close() 4");
336
337	/*
338	 * Create a UNIX domain stream socket, and attach/test/detach a
339	 * write filter on it.
340	 */
341	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
342		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
343	OK("socketpair() 3");
344
345	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
346		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
347	OK("fcntl() 5");
348	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
349		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
350	OK("fcntl() 6");
351
352	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM");
353
354	if (close(sv[0]) == -1)
355		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
356	OK("close() 5");
357	if (close(sv[1]) == -1)
358		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
359	OK("close() 6");
360
361	if (close(kq) == -1)
362		fail(errno, "close", "kq", NULL);
363	OK("close() 7");
364
365	return (0);
366}
367