📄 sockio.c
字号:
if (error) {
/*
* Probably ran out of file descriptors. Put the
* unaccepted connection back onto the queue and
* do another wakeup so some other process might
* have a chance at it.
*/
TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
head->so_qlen++;
wakeup_one(&head->so_timeo);
splx(s);
goto done;
}
fhold(nfp);
p->p_retval[0] = fd;
/* connection has been removed from the listen queue */
KNOTE(&head->so_rcv.sb_sel.si_note, 0);
#endif
so->so_state &= ~SS_COMP;
so->so_head = NULL;
cyg_selinit(&so->so_rcv.sb_sel);
cyg_selinit(&so->so_snd.sb_sel);
new_fp->f_type = DTYPE_SOCKET;
new_fp->f_flag |= FREAD|FWRITE;
new_fp->f_offset = 0;
new_fp->f_ops = &bsd_sock_fileops;
new_fp->f_data = (CYG_ADDRWORD)so;
new_fp->f_xops = (CYG_ADDRWORD)&bsd_sockops;
sa = 0;
error = soaccept(so, &sa);
if (error) {
/*
* return a namelen of zero for older code which might
* ignore the return value from accept.
*/
if (name != NULL) {
*anamelen = 0;
}
goto noconnection;
}
if (sa == NULL) {
namelen = 0;
if (name)
goto gotnoname;
splx(s);
error = 0;
goto done;
}
if (name) {
if (namelen > sa->sa_len)
namelen = sa->sa_len;
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, (caddr_t)name, namelen);
if (!error)
gotnoname:
*anamelen = namelen;
}
noconnection:
#if 0 // FIXME
/*
* close the new descriptor, assuming someone hasn't ripped it
* out from under us.
*/
if (error) {
if (fdp->fd_ofiles[fd] == nfp) {
fdp->fd_ofiles[fd] = NULL;
fdrop(nfp, p);
}
}
splx(s);
/*
* Release explicitly held references before returning.
*/
done:
if (nfp != NULL)
fdrop(nfp, p);
fdrop(lfp, p);
return (error);
m_freem(nam);
#else
done:
splx(s);
if (sa)
FREE(sa, M_SONAME);
#endif
return (error);
}
// -------------------------------------------------------------------------
static int
bsd_listen(cyg_file *fp, int backlog)
{
return (solisten((struct socket *)fp->f_data, backlog, 0));
}
// -------------------------------------------------------------------------
static int
bsd_getname(cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer)
{
struct socket *so;
socklen_t len = 0;
int error;
sockaddr *sa;
if( alen != NULL)
len = *alen;
so = (struct socket *)fp->f_data;
sa = 0;
if (peer) {
// getpeername()
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
return (ENOTCONN);
}
error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
} else {
// getsockname()
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
}
if (error)
goto bad;
if (sa == 0) {
len = 0;
goto gotnothing;
}
len = min(len, sa->sa_len);
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, (caddr_t)asa, (u_int)len);
gotnothing:
*alen = len;
bad:
if (sa)
FREE(sa, M_SONAME);
return (error);
}
// -------------------------------------------------------------------------
static int
bsd_shutdown(cyg_file *fp, int how)
{
return (soshutdown((struct socket *)fp->f_data, how));
}
// -------------------------------------------------------------------------
static int
bsd_getsockopt(cyg_file *fp, int level, int optname,
void *optval, socklen_t *optlen)
{
socklen_t valsize = 0;
int error;
struct sockopt opt;
if( optval != NULL && optlen != NULL)
valsize = *optlen;
opt.sopt_dir = SOPT_GET;
opt.sopt_level = level;
opt.sopt_name = optname;
opt.sopt_val = optval;
opt.sopt_valsize = valsize;
opt.sopt_p = 0;
error = sogetopt((struct socket *)fp->f_data, &opt);
if (error == 0) {
*optlen = opt.sopt_valsize;
}
return (error);
}
// -------------------------------------------------------------------------
static int
bsd_setsockopt(cyg_file *fp, int level, int optname,
const void *optval, socklen_t optlen)
{
struct sockopt opt;
opt.sopt_dir = SOPT_SET;
opt.sopt_level = level;
opt.sopt_name = optname;
opt.sopt_val = (void *)optval;
opt.sopt_valsize = optlen;
opt.sopt_p = 0;
return sosetopt((struct socket *)fp->f_data, &opt);
}
// -------------------------------------------------------------------------
static int
bsd_sendmsg(cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize)
{
return bsd_sendit(fp, m, flags, retsize);
}
// -------------------------------------------------------------------------
static int
bsd_recvmsg(cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize)
{
return bsd_recvit(fp, m, namelen, retsize);
}
//==========================================================================
// File system call functions
// -------------------------------------------------------------------------
static int
bsd_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
return (soreceive((struct socket *)fp->f_data, (struct sockaddr **)0,
uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0));
}
// -------------------------------------------------------------------------
static int
bsd_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
return (sosend((struct socket *)fp->f_data, (struct sockaddr *)0,
uio, (struct mbuf *)0, (struct mbuf *)0, 0, 0));
}
// -------------------------------------------------------------------------
static int
bsd_lseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
{
return ESPIPE;
}
// -------------------------------------------------------------------------
static int
bsd_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data)
{
struct socket *so = (struct socket *)fp->f_data;
void *p = 0;
switch (cmd) {
case FIONBIO:
if (*(int *)data)
so->so_state |= SS_NBIO;
else
so->so_state &= ~SS_NBIO;
return (0);
case FIOASYNC:
if (*(int *)data) {
so->so_state |= SS_ASYNC;
so->so_rcv.sb_flags |= SB_ASYNC;
so->so_snd.sb_flags |= SB_ASYNC;
} else {
so->so_state &= ~SS_ASYNC;
so->so_rcv.sb_flags &= ~SB_ASYNC;
so->so_snd.sb_flags &= ~SB_ASYNC;
}
return (0);
case FIONREAD:
*(int *)data = so->so_rcv.sb_cc;
return (0);
case SIOCATMARK:
*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
return (0);
}
/*
* Interface/routing/protocol specific ioctls:
* interface and routing ioctls should have a
* different entry since a socket's unnecessary
*/
if (IOCGROUP(cmd) == 'i')
return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));
if (IOCGROUP(cmd) == 'r')
return (rtioctl((u_long)cmd, (caddr_t)data, p));
return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, (caddr_t)data, 0, 0));
}
#if 0 // DEBUG support
static int
bsd_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data)
{
int res = _bsd_ioctl(fp, cmd, data);
diag_printf("ioctl(%x,%x) = %x\n", cmd, data, res);
return res;
}
#endif
// -------------------------------------------------------------------------
static int
bsd_select(struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
{
register struct socket *so = (struct socket *)fp->f_data;
register int s = splsoftnet();
switch (which) {
case FREAD:
if (soreadable(so)) {
splx(s);
return (1);
}
cyg_selrecord(info, &so->so_rcv.sb_sel);
so->so_rcv.sb_flags |= SB_SEL;
break;
case FWRITE:
if (sowriteable(so)) {
splx(s);
return (1);
}
cyg_selrecord(info, &so->so_snd.sb_sel);
so->so_snd.sb_flags |= SB_SEL;
break;
case 0:
if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
splx(s);
return (1);
}
cyg_selrecord(info, &so->so_rcv.sb_sel);
so->so_rcv.sb_flags |= SB_SEL;
break;
}
splx(s);
return ENOERR;
}
// -------------------------------------------------------------------------
static int
bsd_fsync(struct CYG_FILE_TAG *fp, int mode)
{
// FIXME: call some sort of flush IOCTL?
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -