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 + -
显示快捷键?