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

📄 sockio.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

// -------------------------------------------------------------------------

static int 
bsd_close(struct CYG_FILE_TAG *fp)
{
    int error = 0;

    if (fp->f_data)
        error = soclose((struct socket *)fp->f_data);
    fp->f_data = 0;
    return (error);
}

// -------------------------------------------------------------------------

static int 
bsd_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
{
    register struct socket *so = (struct socket *)fp->f_data;

    bzero((caddr_t)buf, sizeof (*buf));

    // Mark socket as a fifo for now. We need to add socket types to
    // sys/stat.h.
    buf->st_mode = __stat_mode_FIFO;
    
    return ((*so->so_proto->pr_usrreqs->pru_sense)(so, buf));
}

// -------------------------------------------------------------------------

static int 
bsd_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len)
{
    return ENOSYS;
}

// -------------------------------------------------------------------------

static int 
bsd_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len)
{
    return ENOSYS;
}


#if 0
//==========================================================================
// Select support

// -------------------------------------------------------------------------
// This function is called by the lower layers to record the
// fact that a particular 'select' event is being requested.
//

void        
selrecord(void *selector, struct selinfo *info)
{
    // Unused by this implementation
}

// -------------------------------------------------------------------------
// This function is called to indicate that a 'select' event
// may have occurred.
//

void    
selwakeup(struct selinfo *info)
{
    cyg_selwakeup( info);
}
#endif

//==========================================================================
// Misc support functions

int
sockargs(mp, buf, buflen, type)
	struct mbuf **mp;
	caddr_t buf;
	int buflen;
	int type;
{
	register struct sockaddr *sa;
	register struct mbuf *m;
	int error;

	if (buflen > MLEN) {
#ifdef COMPAT_OLDSOCK
		if (type == MT_SONAME && buflen <= 112)
			buflen = MLEN;		/* unix domain compat. hack */
		else
#endif
		return (EINVAL);
	}
	m = m_get(M_WAIT, type);
	if (m == NULL)
		return (ENOBUFS);
	m->m_len = buflen;
	error = copyin(buf, mtod(m, caddr_t), buflen);
	if (error) {
		(void) m_free(m);
		return (error);
	}
	*mp = m;
	if (type == MT_SONAME) {
		sa = mtod(m, struct sockaddr *);

#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
			sa->sa_family = sa->sa_len;
#endif
		sa->sa_len = buflen;
	}
	return (0);
}


// -------------------------------------------------------------------------
// bsd_recvit()
// Support for message reception. This is a lightly edited version of the
// recvit() function is uipc_syscalls.c.

static int
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize)
{
    struct uio auio;
    struct iovec *iov;
    int i;
    size_t len;
    int error;
    struct mbuf *m, *control = 0;
    caddr_t ctlbuf;
    struct socket *so;
    struct sockaddr *fromsa = 0;

    auio.uio_iov = mp->msg_iov;
    auio.uio_iovcnt = mp->msg_iovlen;
    auio.uio_segflg = UIO_USERSPACE;
    auio.uio_rw = UIO_READ;
    auio.uio_offset = 0;			/* XXX */
    auio.uio_resid = 0;
    iov = mp->msg_iov;
    for (i = 0; i < mp->msg_iovlen; i++, iov++) {
        /* Don't allow sum > SSIZE_MAX */
        if (iov->iov_len > SSIZE_MAX ||
            (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
            return (EINVAL);
    }

    len = auio.uio_resid;
    so = (struct socket *)fp->f_data;
    error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
                                                    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
                                                    &mp->msg_flags);
    if (error) {
        if (auio.uio_resid != len && 
            (error == EINTR || error == EWOULDBLOCK))
            error = 0;
    }
    if (error)
        goto out;
    *retsize = len - auio.uio_resid;
    if (mp->msg_name) {
        len = mp->msg_namelen;
        if (len <= 0 || fromsa == 0)
            len = 0;
        else {
            /* save sa_len before it is destroyed by MSG_COMPAT */
            if (len > fromsa->sa_len)
                len = fromsa->sa_len;
#ifdef COMPAT_OLDSOCK
            if (mp->msg_flags & MSG_COMPAT)
                ((struct osockaddr *)fromsa)->sa_family =
                    fromsa->sa_family;
#endif
            error = copyout(fromsa,
			    (caddr_t)mp->msg_name, (unsigned)len);
            if (error)
                goto out;
        }
        mp->msg_namelen = len;
        if (namelenp) {
            *namelenp = len;
#ifdef COMPAT_OLDSOCK
            if (mp->msg_flags & MSG_COMPAT)
                error = 0;	/* old recvfrom didn't check */
            else
#endif
                goto out;
        }
    }
    if (mp->msg_control) {
#ifdef COMPAT_OLDSOCK
        /*
         * We assume that old recvmsg calls won't receive access
         * rights and other control info, esp. as control info
         * is always optional and those options didn't exist in 4.3.
         * If we receive rights, trim the cmsghdr; anything else
         * is tossed.
         */
        if (control && mp->msg_flags & MSG_COMPAT) {
            if (mtod(control, struct cmsghdr *)->cmsg_level !=
                SOL_SOCKET ||
                mtod(control, struct cmsghdr *)->cmsg_type !=
                SCM_RIGHTS) {
                mp->msg_controllen = 0;
                goto out;
            }
            control->m_len -= sizeof (struct cmsghdr);
            control->m_data += sizeof (struct cmsghdr);
        }
#endif
        len = mp->msg_controllen;
        m = control;
        mp->msg_controllen = 0;
        ctlbuf = (caddr_t) mp->msg_control;

        while (m && len > 0) {
            unsigned int tocopy;

            if (len >= m->m_len) 
                tocopy = m->m_len;
            else {
                mp->msg_flags |= MSG_CTRUNC;
                tocopy = len;
            }
		
            if ((error = copyout((caddr_t)mtod(m, caddr_t),
                                 ctlbuf, tocopy)) != 0)
                goto out;

            ctlbuf += tocopy;
            len -= tocopy;
            m = m->m_next;
        }
        mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
    }
 out:
    if (fromsa)
        FREE(fromsa, M_SONAME);
    if (control)
        m_freem(control);
    return (error);
}

// -------------------------------------------------------------------------
// sendit()
// Support for message transmission. This is a lightly edited version of the
// synonymous function is uipc_syscalls.c.

static int
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize)
{
    struct uio auio;
    register struct iovec *iov;
    register int i;
    struct mbuf *control;
    struct sockaddr *to;
    int len, error;
    struct socket *so;
	
    auio.uio_iov = mp->msg_iov;
    auio.uio_iovcnt = mp->msg_iovlen;
    auio.uio_segflg = UIO_USERSPACE;
    auio.uio_rw = UIO_WRITE;
    auio.uio_offset = 0;			/* XXX */
    auio.uio_resid = 0;
    iov = mp->msg_iov;
    for (i = 0; i < mp->msg_iovlen; i++, iov++) {
        /* Don't allow sum > SSIZE_MAX */
        if (iov->iov_len > SSIZE_MAX ||
            (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
            return (EINVAL);
    }
    if (mp->msg_name) {
        error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
        if (error) {
            return (error);
        }
    } else {
        to = 0;
    }
    if (mp->msg_control) {
        if (mp->msg_controllen < sizeof(struct cmsghdr)
#ifdef COMPAT_OLDSOCK
            && mp->msg_flags != MSG_COMPAT
#endif
            ) {
            error = EINVAL;
            goto bad;
        }
        error = sockargs(&control, mp->msg_control,
                         mp->msg_controllen, MT_CONTROL);
        if (error)
            goto bad;
#ifdef COMPAT_OLDSOCK
        if (mp->msg_flags == MSG_COMPAT) {
            register struct cmsghdr *cm;

            M_PREPEND(control, sizeof(*cm), M_WAIT);
            if (control == 0) {
                error = ENOBUFS;
                goto bad;
            } else {
                cm = mtod(control, struct cmsghdr *);
                cm->cmsg_len = control->m_len;
                cm->cmsg_level = SOL_SOCKET;
                cm->cmsg_type = SCM_RIGHTS;
            }
        }
#endif
    } else
        control = 0;

    len = auio.uio_resid;
    so = (struct socket *)fp->f_data;
    error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
                                                 flags, 0);
    if (error) {
        if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
            error = 0;
    }
    if (error == 0)
        *retsize = len - auio.uio_resid;
 bad:
    if (to)
        FREE(to, M_SONAME);
    return (error);
}

static int
getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
{
	struct sockaddr *sa;
	int error;

	if (len > SOCK_MAXADDRLEN)
		return ENAMETOOLONG;
	MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
	error = copyin(uaddr, sa, len);
	if (error) {
		FREE(sa, M_SONAME);
	} else {
#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
			sa->sa_family = sa->sa_len;
#endif
		sa->sa_len = len;
		*namp = sa;
	}
	return error;
}

//==========================================================================
// End of sockio.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -