xref: /freebsd/tools/regression/sockets/kqueue/kqueue.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 
39 static 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 
59 static void
fail(int error,const char * func,const char * socktype,const char * rest)60 fail(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 
76 static void
fail_assertion(const char * func,const char * socktype,const char * rest,const char * assertion)77 fail_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  */
101 static void
test_evfilt_read(int kq,int fd[2],const char * socktype)102 test_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 
186 static void
test_evfilt_write(int kq,int fd[2],const char * socktype)187 test_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  */
250 int
main(void)251 main(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