sockio.c

来自「eCos操作系统源码」· C语言 代码 · 共 954 行 · 第 1/2 页

C
954
字号
    }        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 functionsintsockargs(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 intbsd_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 intbsd_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 + =
减小字号Ctrl + -
显示快捷键?