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

📄 sockio.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    
    return (sosetopt((struct socket *)fp->f_data, level, optname, m));
}

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

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 mbuf **)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 mbuf *)0,
		uio, (struct mbuf *)0, (struct mbuf *)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)
{
	register 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_usrreq)(so, PRU_CONTROL, 
	    (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));

}

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

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;
}

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

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_usrreq)(so, PRU_SENSE,
                                       (struct mbuf *)buf,
                                       (struct mbuf *)0, 
                                       (struct mbuf *)0));
}

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

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;
}



//==========================================================================
// 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 );
}

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

int
sockargs(mp, buf, buflen, type)
	struct mbuf **mp;
	caddr_t buf;
	socklen_t 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;
	register struct iovec *iov;
	register int i;
	size_t len;
	int error;
	struct mbuf *from = 0, *control = 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;
	error = soreceive((struct socket *)fp->f_data, &from, &auio,
			  NULL, mp->msg_control ? &control : NULL,
			  &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 || from == 0)
			len = 0;
		else {
		        /* save sa_len before it is destroyed by MSG_COMPAT */
			if (len > from->m_len)
				len = from->m_len;
			/* else if len < from->m_len ??? */
#ifdef COMPAT_OLDSOCK
			if (mp->msg_flags & MSG_COMPAT)
				mtod(from, struct osockaddr *)->sa_family =
				    mtod(from, struct sockaddr *)->sa_family;
#endif
			error = copyout(mtod(from, caddr_t),
			    (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;
		if (len <= 0 || control == 0)
			len = 0;
		else {
			struct mbuf *m = control;
			caddr_t p = (caddr_t)mp->msg_control;

			do {
				i = m->m_len;
				if (len < i) {
					mp->msg_flags |= MSG_CTRUNC;
					i = len;
				}
				error = copyout(mtod(m, caddr_t), p,
				    (unsigned)i);
				if (m->m_next)
					i = ALIGN(i);
				p += i;
				len -= i;
				if (error != 0 || len <= 0)
					break;
			} while ((m = m->m_next) != NULL);
			len = p - (caddr_t)mp->msg_control;
		}
		mp->msg_controllen = len;
	}
out:
	if (from)
		m_freem(from);
	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 *to, *control;
	int len, error;
	
	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 = sockargs(&to, mp->msg_name, mp->msg_namelen,
				 MT_SONAME);
		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;
	error = sosend((struct socket *)fp->f_data, to, &auio,
		       NULL, control, flags);
	if (error) {
		if (auio.uio_resid != len && 
                    (error == EINTR || error == EWOULDBLOCK))
			error = 0;
#ifndef __ECOS
		if (error == EPIPE)
			psignal(p, SIGPIPE);
#endif
	}
	if (error == 0)
		*retsize = len - auio.uio_resid;
bad:
	if (to)
		m_freem(to);
	return (error);
}


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

⌨️ 快捷键说明

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