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.
22 #include <sys/queue.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
30 #include "sys/event.h"
34 socket_knote_create(int port, int filter, int fd, void *udata)
46 dbg_puts("invalid filter");
50 rv = port_associate(port, PORT_SOURCE_FD, fd, events, udata);
52 dbg_perror("port_associate(2)");
60 socket_knote_delete(int port, int fd)
62 if (port_dissociate(port, PORT_SOURCE_FD, fd) < 0) {
63 dbg_perror("port_dissociate(2)");
71 evfilt_socket_init(struct filter *filt)
77 evfilt_socket_destroy(struct filter *filt)
83 evfilt_socket_knote_create(struct filter *filt, struct knote *kn)
85 return socket_knote_create(filt->kf_kqueue->kq_port,
86 kn->kev.filter, kn->kev.ident, filt);
90 evfilt_socket_knote_modify(struct filter *filt, struct knote *kn,
91 const struct kevent *kev)
93 return (-1); /* STUB */
97 evfilt_socket_knote_delete(struct filter *filt, struct knote *kn)
99 if (kn->kev.flags & EV_DISABLE)
102 return (socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident));
106 evfilt_socket_knote_enable(struct filter *filt, struct knote *kn)
108 return socket_knote_create(filt->kf_kqueue->kq_port,
109 kn->kev.filter, kn->kev.ident, filt);
113 evfilt_socket_knote_disable(struct filter *filt, struct knote *kn)
115 return socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident);
119 evfilt_socket_copyout(struct filter *filt,
123 port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event);
126 kn = knote_lookup(filt, pe->portev_object);
130 memcpy(dst, &kn->kev, sizeof(*dst));
131 if (pe->portev_events == 8) //XXX-FIXME Should be POLLHUP)
132 dst->flags |= EV_EOF;
133 else if (pe->portev_events & POLLERR)
134 dst->fflags = 1; /* FIXME: Return the actual socket error */
136 if (pe->portev_events & POLLIN) {
137 if (kn->flags & KNFL_PASSIVE_SOCKET) {
138 /* On return, data contains the length of the
139 socket backlog. This is not available under Solaris (?).
143 /* On return, data contains the number of bytes of protocol
144 data available to read.
147 if (ioctl(dst->ident,
148 (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ,
150 /* race condition with socket close, so ignore this error */
151 dbg_puts("ioctl(2) of socket failed");
161 if (kn->kev.flags & EV_DISPATCH) {
162 socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident);
164 } else if (kn->kev.flags & EV_ONESHOT) {
165 socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident);
166 knote_free(filt, kn);
168 /* Solaris automatically disassociates a FD event after it
169 is delivered. This effectively disables the knote. */
176 const struct filter evfilt_read = {
179 evfilt_socket_destroy,
180 evfilt_socket_copyout,
181 evfilt_socket_knote_create,
182 evfilt_socket_knote_modify,
183 evfilt_socket_knote_delete,
184 evfilt_socket_knote_enable,
185 evfilt_socket_knote_disable,
188 const struct filter evfilt_write = {
191 evfilt_socket_destroy,
192 evfilt_socket_copyout,
193 evfilt_socket_knote_create,
194 evfilt_socket_knote_modify,
195 evfilt_socket_knote_delete,
196 evfilt_socket_knote_enable,
197 evfilt_socket_knote_disable,