1/* 2 * Copyright (c) 2009 Mark Heily <mark@heily.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include <arpa/inet.h> 18#include <sys/socket.h> 19#include "common.h" 20 21static int __thread kqfd; 22static int __thread sockfd[2]; 23 24static void 25kevent_socket_drain(void) 26{ 27 char buf[1]; 28 29 /* Drain the read buffer, then make sure there are no more events. */ 30 if (read(sockfd[0], &buf[0], 1) < 1) 31 die("read(2)"); 32} 33 34static void 35kevent_socket_fill(void) 36{ 37 if (write(sockfd[1], ".", 1) < 1) 38 die("write(2)"); 39} 40 41 42void 43test_kevent_socket_add(void) 44{ 45 struct kevent kev; 46 47 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 48} 49 50void 51test_kevent_socket_add_without_ev_add(void) 52{ 53 struct kevent kev; 54 55 /* Try to add a kevent without specifying EV_ADD */ 56 EV_SET(&kev, sockfd[0], EVFILT_READ, 0, 0, 0, &sockfd[0]); 57 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) 58 die("kevent should have failed"); 59 60 kevent_socket_fill(); 61 test_no_kevents(kqfd); 62 kevent_socket_drain(); 63 64 /* Try to delete a kevent which does not exist */ 65 kev.flags = EV_DELETE; 66 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) 67 die("kevent should have failed"); 68} 69 70void 71test_kevent_socket_get(void) 72{ 73 struct kevent kev; 74 75 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 76 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 77 die("kevent"); 78 79 kevent_socket_fill(); 80 81 kev.data = 1; 82 kevent_cmp(&kev, kevent_get(kqfd)); 83 84 kevent_socket_drain(); 85 test_no_kevents(kqfd); 86 87 kev.flags = EV_DELETE; 88 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 89 die("kevent"); 90} 91 92void 93test_kevent_socket_clear(void) 94{ 95 struct kevent kev; 96 97 test_no_kevents(kqfd); 98 kevent_socket_drain(); 99 100 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); 101 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 102 die("kevent"); 103 104 kevent_socket_fill(); 105 kevent_socket_fill(); 106 107/* Solaris does not offer a way to get the amount of data pending */ 108#if defined(__sun__) 109 kev.data = 1; 110#else 111 kev.data = 2; 112#endif 113 kevent_cmp(&kev, kevent_get(kqfd)); 114 115 /* We filled twice, but drain once. Edge-triggered would not generate 116 additional events. 117 */ 118 kevent_socket_drain(); 119 test_no_kevents(kqfd); 120 121 kevent_socket_drain(); 122 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 123 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 124 die("kevent"); 125} 126 127void 128test_kevent_socket_disable_and_enable(void) 129{ 130 struct kevent kev; 131 132 /* Add an event, then disable it. */ 133 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 134 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 135 die("kevent"); 136 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); 137 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 138 die("kevent"); 139 140 kevent_socket_fill(); 141 test_no_kevents(kqfd); 142 143 /* Re-enable the knote, then see if an event is generated */ 144 kev.flags = EV_ENABLE; 145 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 146 die("kevent"); 147 kev.flags = EV_ADD; 148 kev.data = 1; 149 kevent_cmp(&kev, kevent_get(kqfd)); 150 151 kevent_socket_drain(); 152 153 kev.flags = EV_DELETE; 154 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 155 die("kevent"); 156} 157 158void 159test_kevent_socket_del(void) 160{ 161 struct kevent kev; 162 163 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 164 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 165 die("kevent"); 166 167 kevent_socket_fill(); 168 test_no_kevents(kqfd); 169 kevent_socket_drain(); 170} 171 172void 173test_kevent_socket_oneshot(void) 174{ 175 struct kevent kev; 176 177 /* Re-add the watch and make sure no events are pending */ 178 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); 179 test_no_kevents(kqfd); 180 181 kevent_socket_fill(); 182 kev.data = 1; 183 kevent_cmp(&kev, kevent_get(kqfd)); 184 185 test_no_kevents(kqfd); 186 187 /* Verify that the event has been deleted */ 188 kevent_socket_fill(); 189 test_no_kevents(kqfd); 190 kevent_socket_drain(); 191} 192 193/* 194 * Test if the data field returns 1 when a listen(2) socket has 195 * a pending connection. 196 */ 197void 198test_kevent_socket_listen_backlog(void) 199{ 200 struct kevent kev; 201 struct sockaddr_in sain; 202 socklen_t sa_len = sizeof(sain); 203 int one = 1; 204 const short port = 14973; 205 int clnt, srvr; 206 207 /* Create a passive socket */ 208 memset(&sain, 0, sizeof(sain)); 209 sain.sin_family = AF_INET; 210 sain.sin_port = htons(port); 211 if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) abort(); 212 if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, 213 (char *) &one, sizeof(one)) != 0) abort(); 214 if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) abort(); 215 if (listen(srvr, 100) < 0) abort(); 216 217 /* Watch for events on the socket */ 218 test_no_kevents(kqfd); 219 kevent_add(kqfd, &kev, srvr, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL); 220 test_no_kevents(kqfd); 221 222 /* Simulate a client connecting to the server */ 223 sain.sin_family = AF_INET; 224 sain.sin_port = htons(port); 225 sain.sin_addr.s_addr = inet_addr("127.0.0.1"); 226 if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) abort(); 227 if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) abort(); 228 229 /* Verify that data=1 */ 230 kev.data = 1; 231 kevent_cmp(&kev, kevent_get(kqfd)); 232 test_no_kevents(kqfd); 233} 234 235#if HAVE_EV_DISPATCH 236void 237test_kevent_socket_dispatch(void) 238{ 239 struct kevent kev; 240 241 /* Re-add the watch and make sure no events are pending */ 242 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); 243 test_no_kevents(kqfd); 244 245 /* The event will occur only once, even though EV_CLEAR is not 246 specified. */ 247 kevent_socket_fill(); 248 kev.data = 1; 249 kevent_cmp(&kev, kevent_get(kqfd)); 250 test_no_kevents(kqfd); 251 252 /* Re-enable the kevent */ 253 /* FIXME- is EV_DISPATCH needed when rearming ? */ 254 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &sockfd[0]); 255 kev.data = 1; 256 kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ 257 kevent_cmp(&kev, kevent_get(kqfd)); 258 test_no_kevents(kqfd); 259 260 /* Since the knote is disabled, the EV_DELETE operation succeeds. */ 261 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 262 263 kevent_socket_drain(); 264} 265#endif /* HAVE_EV_DISPATCH */ 266 267#if BROKEN_ON_LINUX 268void 269test_kevent_socket_lowat(void) 270{ 271 struct kevent kev; 272 273 test_begin(test_id); 274 275 /* Re-add the watch and make sure no events are pending */ 276 puts("-- re-adding knote, setting low watermark to 2 bytes"); 277 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); 278 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 279 die("%s", test_id); 280 test_no_kevents(); 281 282 puts("-- checking that one byte does not trigger an event.."); 283 kevent_socket_fill(); 284 test_no_kevents(); 285 286 puts("-- checking that two bytes triggers an event.."); 287 kevent_socket_fill(); 288 if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) 289 die("%s", test_id); 290 KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); 291 test_no_kevents(); 292 293 kevent_socket_drain(); 294 kevent_socket_drain(); 295} 296#endif 297 298void 299test_kevent_socket_eof(void) 300{ 301 struct kevent kev; 302 303 /* Re-add the watch and make sure no events are pending */ 304 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 305 test_no_kevents(kqfd); 306 307 if (close(sockfd[1]) < 0) 308 die("close(2)"); 309 310 kev.flags |= EV_EOF; 311 kevent_cmp(&kev, kevent_get(kqfd)); 312 313 /* Delete the watch */ 314 kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 315} 316 317void 318test_evfilt_read(int _kqfd) 319{ 320 /* Create a connected pair of full-duplex sockets for testing socket events */ 321 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 322 die("socketpair"); 323 324 kqfd = _kqfd; 325 test(kevent_socket_add); 326 test(kevent_socket_del); 327 test(kevent_socket_add_without_ev_add); 328 test(kevent_socket_get); 329 test(kevent_socket_disable_and_enable); 330 test(kevent_socket_oneshot); 331 test(kevent_socket_clear); 332#if HAVE_EV_DISPATCH 333 test(kevent_socket_dispatch); 334#endif 335 test(kevent_socket_listen_backlog); 336 test(kevent_socket_eof); 337 close(sockfd[0]); 338 close(sockfd[1]); 339} 340