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