⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockio.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -