sockio.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,076 行 · 第 1/2 页
C
1,076 行
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 supportstatic 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;}// -------------------------------------------------------------------------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 functionsintsockargs(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 intbsd_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 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 *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 intgetsockaddr(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 + =
减小字号Ctrl + -
显示快捷键?