| version 1.71, 2002/08/21 05:13:37 |
version 1.72, 2002/10/23 09:14:28 |
| Line 91 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| Line 91 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| #include <sys/signalvar.h> |
#include <sys/signalvar.h> |
| #include <sys/resourcevar.h> |
#include <sys/resourcevar.h> |
| #include <sys/pool.h> |
#include <sys/pool.h> |
| |
#include <sys/event.h> |
| |
|
| #include <uvm/uvm.h> |
#include <uvm/uvm.h> |
| |
|
| Line 1468 sohasoutofband(struct socket *so) |
|
| Line 1469 sohasoutofband(struct socket *so) |
|
| psignal(p, SIGURG); |
psignal(p, SIGURG); |
| selwakeup(&so->so_rcv.sb_sel); |
selwakeup(&so->so_rcv.sb_sel); |
| } |
} |
| |
|
| |
static void |
| |
filt_sordetach(struct knote *kn) |
| |
{ |
| |
struct socket *so; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
SLIST_REMOVE(&so->so_rcv.sb_sel.si_klist, kn, knote, kn_selnext); |
| |
if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_klist)) |
| |
so->so_rcv.sb_flags &= ~SB_KNOTE; |
| |
} |
| |
|
| |
/*ARGSUSED*/ |
| |
static int |
| |
filt_soread(struct knote *kn, long hint) |
| |
{ |
| |
struct socket *so; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
kn->kn_data = so->so_rcv.sb_cc; |
| |
if (so->so_state & SS_CANTRCVMORE) { |
| |
kn->kn_flags |= EV_EOF; |
| |
kn->kn_fflags = so->so_error; |
| |
return (1); |
| |
} |
| |
if (so->so_error) /* temporary udp error */ |
| |
return (1); |
| |
if (kn->kn_sfflags & NOTE_LOWAT) |
| |
return (kn->kn_data >= kn->kn_sdata); |
| |
return (kn->kn_data >= so->so_rcv.sb_lowat); |
| |
} |
| |
|
| |
static void |
| |
filt_sowdetach(struct knote *kn) |
| |
{ |
| |
struct socket *so; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
SLIST_REMOVE(&so->so_snd.sb_sel.si_klist, kn, knote, kn_selnext); |
| |
if (SLIST_EMPTY(&so->so_snd.sb_sel.si_klist)) |
| |
so->so_snd.sb_flags &= ~SB_KNOTE; |
| |
} |
| |
|
| |
/*ARGSUSED*/ |
| |
static int |
| |
filt_sowrite(struct knote *kn, long hint) |
| |
{ |
| |
struct socket *so; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
kn->kn_data = sbspace(&so->so_snd); |
| |
if (so->so_state & SS_CANTSENDMORE) { |
| |
kn->kn_flags |= EV_EOF; |
| |
kn->kn_fflags = so->so_error; |
| |
return (1); |
| |
} |
| |
if (so->so_error) /* temporary udp error */ |
| |
return (1); |
| |
if (((so->so_state & SS_ISCONNECTED) == 0) && |
| |
(so->so_proto->pr_flags & PR_CONNREQUIRED)) |
| |
return (0); |
| |
if (kn->kn_sfflags & NOTE_LOWAT) |
| |
return (kn->kn_data >= kn->kn_sdata); |
| |
return (kn->kn_data >= so->so_snd.sb_lowat); |
| |
} |
| |
|
| |
/*ARGSUSED*/ |
| |
static int |
| |
filt_solisten(struct knote *kn, long hint) |
| |
{ |
| |
struct socket *so; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
|
| |
/* |
| |
* Set kn_data to number of incoming connections, not |
| |
* counting partial (incomplete) connections. |
| |
*/ |
| |
kn->kn_data = so->so_qlen; |
| |
return (kn->kn_data > 0); |
| |
} |
| |
|
| |
static const struct filterops solisten_filtops = |
| |
{ 1, NULL, filt_sordetach, filt_solisten }; |
| |
static const struct filterops soread_filtops = |
| |
{ 1, NULL, filt_sordetach, filt_soread }; |
| |
static const struct filterops sowrite_filtops = |
| |
{ 1, NULL, filt_sowdetach, filt_sowrite }; |
| |
|
| |
int |
| |
soo_kqfilter(struct file *fp, struct knote *kn) |
| |
{ |
| |
struct socket *so; |
| |
struct sockbuf *sb; |
| |
|
| |
so = (struct socket *)kn->kn_fp->f_data; |
| |
switch (kn->kn_filter) { |
| |
case EVFILT_READ: |
| |
if (so->so_options & SO_ACCEPTCONN) |
| |
kn->kn_fop = &solisten_filtops; |
| |
else |
| |
kn->kn_fop = &soread_filtops; |
| |
sb = &so->so_rcv; |
| |
break; |
| |
case EVFILT_WRITE: |
| |
kn->kn_fop = &sowrite_filtops; |
| |
sb = &so->so_snd; |
| |
break; |
| |
default: |
| |
return (1); |
| |
} |
| |
SLIST_INSERT_HEAD(&sb->sb_sel.si_klist, kn, kn_selnext); |
| |
sb->sb_flags |= SB_KNOTE; |
| |
return (0); |
| |
} |
| |
|