xref: /freebsd/tools/regression/sockets/kqueue/kqueue.c (revision cec50dea12481dc578c0805c887ab2097e1c06c5)
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$
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 
56 static void
57 fail(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 
73 static void
74 fail_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  */
98 static void
99 test_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 
171 static void
172 test_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  */
227 int
228 main(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 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
244 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
245 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
246 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
247 
248 	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM");
249 
250 	if (close(sv[0]) == -1)
251 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
252 	if (close(sv[1]) == -1)
253 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
254 
255 #if 0
256 	/*
257 	 * XXXRW: We disable the write test in the case of datagram sockets,
258 	 * as kqueue can't tell when the remote socket receive buffer is
259 	 * full, whereas the UNIX domain socket implementation can tell and
260 	 * returns ENOBUFS.
261 	 */
262 	/*
263 	 * Create a UNIX domain datagram socket, and attach/test/detach a
264 	 * write filter on it.
265 	 */
266 	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
267 		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
268 
269 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
270 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
271 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
272 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
273 
274 	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM");
275 
276 	if (close(sv[0]) == -1)
277 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
278 	if (close(sv[1]) == -1)
279 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
280 #endif
281 
282 	/*
283 	 * Create a UNIX domain stream socket, and attach/test/detach a
284 	 * read filter on it.
285 	 */
286 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
287 		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
288 
289 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
290 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
291 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
292 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
293 
294 	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM");
295 
296 	if (close(sv[0]) == -1)
297 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
298 	if (close(sv[1]) == -1)
299 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
300 
301 	/*
302 	 * Create a UNIX domain stream socket, and attach/test/detach a
303 	 * write filter on it.
304 	 */
305 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
306 		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
307 
308 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
309 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
310 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
311 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
312 
313 	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM");
314 
315 	if (close(sv[0]) == -1)
316 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
317 	if (close(sv[1]) == -1)
318 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
319 
320 	if (close(kq) == -1)
321 		fail(errno, "close", "kq", NULL);
322 
323 	printf("PASS\n");
324 	return (0);
325 }
326