Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/regression/sockets/kqueue/kqueue.c
48254 views
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
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
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
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
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
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
368