sockio.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,076 行 · 第 1/2 页
C
1,076 行
//==========================================================================//// src/sys/kern/sockio.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//==========================================================================//// 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, gthomas// Date: 2000-06-06// Purpose: // Description: File I/O operations for network sockets. Ruthelessly// cribbed from the BSD sources and adapted to eCos.////####DESCRIPTIONEND####////==========================================================================/* * Copyright (c) 1982, 1986, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * * sendfile(2) and related extensions: * Copyright (c) 1998, David Greenman. All rights reserved. * * 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. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 * $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.9 2001/07/31 10:49:39 dwmalone Exp $ *///==========================================================================#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/malloc.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 int bsd_recvit (cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize);static int bsd_sendit (cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize);static int getsockaddr (struct sockaddr **namp, caddr_t uaddr, size_t len);//==========================================================================// 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, (struct proc *)&proc0); 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){ int error; error = sobind((struct socket *)fp->f_data, (sockaddr *)sa, 0); return error;}// -------------------------------------------------------------------------static int bsd_connect(cyg_file *fp, const sockaddr *sa, socklen_t len){ struct socket *so; sockaddr sa1=*sa; int error, s; sa1.sa_len = len; so = (struct socket *)fp->f_data; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) return (EALREADY); error = soconnect(so, (struct sockaddr *)&sa1, 0); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 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; return error;}// -------------------------------------------------------------------------static int bsd_accept(cyg_file *fp, cyg_file *new_fp, struct sockaddr *name, socklen_t *anamelen){ socklen_t namelen = 0; int error = 0, s; struct socket *head, *so; struct sockaddr *sa; if( anamelen != NULL) namelen = *anamelen; s = splsoftnet(); head = (struct socket *)fp->f_data; if ((head->so_options & SO_ACCEPTCONN) == 0) { splx(s); return (EINVAL); } if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { splx(s); return (EWOULDBLOCK); } while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) { if (head->so_state & SS_CANTRCVMORE) { head->so_error = ECONNABORTED; break; } error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH, "netcon", 0); if (error) { splx(s); return (error); } } if (head->so_error) { error = head->so_error; head->so_error = 0; splx(s); return (error); } /* * At this point we know that there is at least one connection * ready to be accepted. Remove it from the queue prior to * allocating the file descriptor for it since falloc() may * block allowing another process to accept the connection * instead. */ so = TAILQ_FIRST(&head->so_comp); TAILQ_REMOVE(&head->so_comp, so, so_list); head->so_qlen--;#if 0 // FIXME fflag = lfp->f_flag; error = falloc(p, &nfp, &fd); if (error) { /* * Probably ran out of file descriptors. Put the * unaccepted connection back onto the queue and * do another wakeup so some other process might * have a chance at it. */ TAILQ_INSERT_HEAD(&head->so_comp, so, so_list); head->so_qlen++; wakeup_one(&head->so_timeo); splx(s); goto done; } fhold(nfp); p->p_retval[0] = fd; /* connection has been removed from the listen queue */ KNOTE(&head->so_rcv.sb_sel.si_note, 0);#endif so->so_state &= ~SS_COMP; so->so_head = NULL; 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; sa = 0; error = soaccept(so, &sa); if (error) { /* * return a namelen of zero for older code which might * ignore the return value from accept. */ if (name != NULL) { *anamelen = 0; } goto noconnection; } if (sa == NULL) { namelen = 0; if (name) goto gotnoname; splx(s); error = 0; goto done; } if (name) { if (namelen > sa->sa_len) namelen = sa->sa_len;#ifdef COMPAT_OLDSOCK if (compat) ((struct osockaddr *)sa)->sa_family = sa->sa_family;#endif error = copyout(sa, (caddr_t)name, namelen); if (!error)gotnoname: *anamelen = namelen; }noconnection:#if 0 // FIXME /* * close the new descriptor, assuming someone hasn't ripped it * out from under us. */ if (error) { if (fdp->fd_ofiles[fd] == nfp) { fdp->fd_ofiles[fd] = NULL; fdrop(nfp, p); } } splx(s); /* * Release explicitly held references before returning. */done: if (nfp != NULL) fdrop(nfp, p); fdrop(lfp, p); return (error); m_freem(nam);#else done: splx(s); if (sa) FREE(sa, M_SONAME);#endif return (error);}// -------------------------------------------------------------------------static int bsd_listen(cyg_file *fp, int backlog){ return (solisten((struct socket *)fp->f_data, backlog, 0));}// -------------------------------------------------------------------------static int bsd_getname(cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer){ struct socket *so; socklen_t len = 0; int error; sockaddr *sa; if( alen != NULL) len = *alen; so = (struct socket *)fp->f_data; sa = 0; if (peer) { // getpeername() if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { return (ENOTCONN); } error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa); } else { // getsockname() error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa); } if (error) goto bad; if (sa == 0) { len = 0; goto gotnothing; } len = min(len, sa->sa_len);#ifdef COMPAT_OLDSOCK if (compat) ((struct osockaddr *)sa)->sa_family = sa->sa_family;#endif error = copyout(sa, (caddr_t)asa, (u_int)len); gotnothing: *alen = len; bad: if (sa) FREE(sa, M_SONAME); 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){ socklen_t valsize = 0; int error; struct sockopt opt; if( optval != NULL && optlen != NULL) valsize = *optlen; opt.sopt_dir = SOPT_GET; opt.sopt_level = level; opt.sopt_name = optname; opt.sopt_val = optval; opt.sopt_valsize = valsize; opt.sopt_p = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?