sockio.c
来自「eCos操作系统源码」· C语言 代码 · 共 954 行 · 第 1/2 页
C
954 行
//==========================================================================//// sys/kern/sockio.c//// Socket interface to Fileio subsystem////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg// Date: 2000-06-06// Purpose: // Description: // ////####DESCRIPTIONEND####////==========================================================================/* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *///==========================================================================#include <pkgconf/net.h>#include <pkgconf/io_fileio.h>#include <sys/types.h>#include <cyg/io/file.h>#include <cyg/fileio/fileio.h>#include <cyg/fileio/sockio.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/ioctl.h>#include <net/if.h>#include <net/route.h>//==========================================================================// Forward definitionsstatic int bsd_init( cyg_nstab_entry *nste );static int bsd_socket( cyg_nstab_entry *nste, int domain, int type, int protocol, cyg_file *file );static int bsd_bind ( cyg_file *fp, const sockaddr *sa, socklen_t len );static int bsd_connect ( cyg_file *fp, const sockaddr *sa, socklen_t len );static int bsd_accept ( cyg_file *fp, cyg_file *new_fp, struct sockaddr *name, socklen_t *anamelen );static int bsd_listen ( cyg_file *fp, int len );static int bsd_getname ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );static int bsd_shutdown ( cyg_file *fp, int flags );static int bsd_getsockopt( cyg_file *fp, int level, int optname, void *optval, socklen_t *optlen);static int bsd_setsockopt( cyg_file *fp, int level, int optname, const void *optval, socklen_t optlen);static int bsd_sendmsg ( cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize );static int bsd_recvmsg ( cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize );// File operationsstatic int bsd_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int bsd_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int bsd_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );static int bsd_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data);static int bsd_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);static int bsd_fsync (struct CYG_FILE_TAG *fp, int mode ); static int bsd_close (struct CYG_FILE_TAG *fp);static int bsd_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );static int bsd_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );static int bsd_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );static intbsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize);static intbsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize);//==========================================================================// Table entrysNSTAB_ENTRY( bsd_nste, 0, "bsd_tcpip", "", 0, bsd_init, bsd_socket);struct cyg_sock_ops bsd_sockops ={ bsd_bind, bsd_connect, bsd_accept, bsd_listen, bsd_getname, bsd_shutdown, bsd_getsockopt, bsd_setsockopt, bsd_sendmsg, bsd_recvmsg};cyg_fileops bsd_sock_fileops ={ bsd_read, bsd_write, bsd_lseek, bsd_ioctl, bsd_select, bsd_fsync, bsd_close, bsd_fstat, bsd_getinfo, bsd_setinfo };//==========================================================================// NStab functions// -------------------------------------------------------------------------static int bsd_init( cyg_nstab_entry *nste ){ // Initialization already handled via constructor return ENOERR;}// -------------------------------------------------------------------------static int bsd_socket( cyg_nstab_entry *nste, int domain, int type, int protocol, cyg_file *file ){ int error = 0; struct socket *so; error = socreate( domain, &so, type, protocol ); if( error == ENOERR ) { cyg_selinit(&so->so_rcv.sb_sel); cyg_selinit(&so->so_snd.sb_sel); file->f_flag |= CYG_FREAD|CYG_FWRITE; file->f_type = CYG_FILE_TYPE_SOCKET; file->f_ops = &bsd_sock_fileops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)so; file->f_xops = (CYG_ADDRWORD)&bsd_sockops; } return error;}//==========================================================================// Sockops functions// -------------------------------------------------------------------------static int bsd_bind ( cyg_file *fp, const sockaddr *sa, socklen_t len ){ struct mbuf *nam; int error; error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME); if (error) return (error); error = sobind((struct socket *)fp->f_data, nam); m_freem(nam); return error;}// -------------------------------------------------------------------------static int bsd_connect ( cyg_file *fp, const sockaddr *sa, socklen_t len ){ register struct socket *so; struct mbuf *nam; int error, s; so = (struct socket *)fp->f_data; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) return (EALREADY); error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME); if (error) return (error); error = soconnect(so, nam); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { m_freem(nam); return (EINPROGRESS); } s = splsoftnet(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, netcon, 0); if (error) break; } if (error == 0) { error = so->so_error; so->so_error = 0; } splx(s);bad: so->so_state &= ~SS_ISCONNECTING; m_freem(nam); return error;}// -------------------------------------------------------------------------static int bsd_accept ( cyg_file *fp, cyg_file *new_fp, struct sockaddr *name, socklen_t *anamelen ){ struct mbuf *nam; socklen_t namelen = 0; int error = 0, s; register struct socket *so; if( anamelen != NULL ) namelen = *anamelen; s = splsoftnet(); so = (struct socket *)fp->f_data; if ((so->so_options & SO_ACCEPTCONN) == 0) { splx(s); return (EINVAL); } if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { splx(s); return (EWOULDBLOCK); } while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; break; } error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, netcon, 0); if (error) { splx(s); return (error); } } if (so->so_error) { error = so->so_error; so->so_error = 0; splx(s); return (error); } { struct socket *aso = so->so_q; if (soqremque(aso, 1) == 0) panic("accept"); so = aso; } 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; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); if (name) { if (namelen > nam->m_len) namelen = nam->m_len; /* SHOULD COPY OUT A CHAIN HERE */ if ((error = copyout(mtod(nam, caddr_t), (caddr_t)name, namelen)) == 0) *anamelen = namelen; } m_freem(nam); splx(s); return (error);}// -------------------------------------------------------------------------static int bsd_listen ( cyg_file *fp, int backlog ){ return (solisten((struct socket *)fp->f_data, backlog));}// -------------------------------------------------------------------------static int bsd_getname ( cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer ){ register struct socket *so; struct mbuf *m; socklen_t len = 0; int error; int type = peer ? PRU_PEERADDR : PRU_SOCKADDR; if( alen != NULL ) len = *alen; so = (struct socket *)fp->f_data; if ( peer && (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) return (ENOTCONN); m = m_getclr(M_WAIT, MT_SONAME); if (m == NULL) return (ENOBUFS); error = (*so->so_proto->pr_usrreq)(so, type, 0, m, 0); if (error) goto bad; if (len > m->m_len) len = m->m_len; error = copyout(mtod(m, caddr_t), (caddr_t)asa, len); if (error == 0) *alen = len;bad: m_freem(m); 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){ struct mbuf *m = NULL; socklen_t valsize = 0; int error; if( optval != NULL && optlen != NULL ) valsize = *optlen; error = sogetopt((struct socket *)fp->f_data, level, optname, &m); if( error == ENOERR && valsize != 0 && m != NULL) { if (valsize > m->m_len) valsize = m->m_len; error = copyout(mtod(m, caddr_t), optval, valsize); if( error == ENOERR ) *optlen = valsize; } if (m != NULL) (void) m_free(m); return (error);}// -------------------------------------------------------------------------static int bsd_setsockopt( cyg_file *fp, int level, int optname, const void *optval, socklen_t optlen){ int error; struct mbuf *m = NULL; if( optlen > MCLBYTES ) return EINVAL; if (optval != NULL) { m = m_get(M_WAIT, MT_SOOPTS); if (optlen > MLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); return (ENOBUFS); } } if (m == NULL) return (ENOBUFS); error = copyin(optval, mtod(m, caddr_t), optlen); if (error) { (void) m_free(m); return (error); } m->m_len = optlen;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?