2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
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.
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.
19 #include <sys/queue.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
27 knote_cmp(struct knote *a, struct knote *b)
29 return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident));
32 RB_GENERATE(knt, knote, kntree_ent, knote_cmp)
39 if ((dst = calloc(1, sizeof(*dst))) == NULL)
46 knote_insert(struct filter *filt, struct knote *kn)
48 RB_INSERT(knt, &filt->kf_knote, kn);
52 knote_free(struct filter *filt, struct knote *kn)
54 dbg_printf("filter=%s, ident=%u",
55 filter_name(kn->kev.filter), (unsigned int) kn->kev.ident);
56 RB_REMOVE(knt, &filt->kf_knote, kn);
57 if (kn->event_ent.tqe_prev) //XXX-FIXME what if this is the 1st entry??
58 TAILQ_REMOVE(&filt->kf_event, kn, event_ent);
59 filt->kn_delete(filt, kn);
64 knote_free_all(struct filter *filt)
66 struct knote *n1, *n2;
68 /* Destroy all pending events */
69 for (n1 = TAILQ_FIRST(&filt->kf_event); n1 != NULL; n1 = n2) {
70 n2 = TAILQ_NEXT(n1, event_ent);
74 /* Distroy all knotes */
75 for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) {
76 n2 = RB_NEXT(knt, filt->kf_knote, n1);
77 RB_REMOVE(knt, &filt->kf_knote, n1);
82 /* TODO: rename to knote_lookup_ident */
84 knote_lookup(struct filter *filt, short ident)
87 struct knote *ent = NULL;
89 query.kev.ident = ident;
90 ent = RB_FIND(knt, &filt->kf_knote, &query);
92 dbg_printf("id=%d ent=%p", ident, ent);
98 knote_lookup_data(struct filter *filt, intptr_t data)
102 RB_FOREACH(kn, knt, &filt->kf_knote) {
103 if (data == kn->kev.data)
110 knote_enqueue(struct filter *filt, struct knote *kn)
112 /* XXX-FIXME: check if the knote is already on the eventlist */
113 TAILQ_INSERT_TAIL(&filt->kf_event, kn, event_ent);
117 knote_dequeue(struct filter *filt)
121 if (TAILQ_EMPTY(&filt->kf_event)) {
123 dbg_puts("no events are pending");
125 kn = TAILQ_FIRST(&filt->kf_event);
126 TAILQ_REMOVE(&filt->kf_event, kn, event_ent);
127 memset(&kn->event_ent, 0, sizeof(kn->event_ent));
134 knote_events_pending(struct filter *filt)
138 res = TAILQ_EMPTY(&filt->kf_event);
144 * Test if a socket is active or passive.
147 knote_get_socket_type(struct knote *kn)
152 slen = sizeof(lsock);
154 i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, &lsock, &slen);
157 case ENOTSOCK: /* same as lsock = 0 */
161 dbg_printf("getsockopt(3) failed: %s", strerror(errno));
166 kn->flags |= KNFL_PASSIVE_SOCKET;