📄 bsdsocklib.c
字号:
) { struct mbuf *nam; int namelen = *addrlen; int slev; FAST struct socket *so; FAST int fd;#ifndef _WRS_VXWORKS_5_X OBJ_ID fdObject; STATUS status;#endif /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ slev = splnet (); if ((so->so_options & SO_ACCEPTCONN) == 0) { netErrnoSet (EINVAL); splx (slev); return (ERROR); } if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { netErrnoSet (EWOULDBLOCK); splx(slev); return (ERROR); } while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; break; } ksleep (so->so_timeoSem); } if (so->so_error) { netErrnoSet ((int) so->so_error); so->so_error = 0; splx (slev); return (ERROR); } if ( (nam = mBufClGet (M_WAIT, MT_SONAME, CL_SIZE_128, TRUE)) == NULL) { netErrnoSet (ENOBUFS); splx (slev); return (ERROR); } { struct socket *aso = so->so_q; if (soqremque(aso, 1) == 0) panic ("accept"); so = aso; } (void) soaccept (so, nam); if (addr) { if (namelen > nam->m_len) namelen = nam->m_len; /* XXX SHOULD COPY OUT A CHAIN HERE */ (void) copyout (mtod(nam, caddr_t), (caddr_t)addr, namelen); (void) copyout ((caddr_t)&namelen, (caddr_t)addrlen, sizeof (*addrlen)); if (bsdSock43ApiFlag) { /* Convert the address structure contents to the BSD 4.3 format. */ bsdSockAddrRevert (addr); } } m_freem (nam); splx (slev); /* put the new socket into an fd */ if ((fd = iosFdNew ((DEV_HDR *) &bsdSockDev, bsdSockName, (int) so)) == ERROR) { (void)bsdSockClose (so); return (ERROR); }#ifndef _WRS_VXWORKS_5_X /* set ownership of socket semaphores */ fdObject = iosFdObjIdGet (fd); if (fdObject == NULL) { (void)bsdSockClose (so); return (ERROR); } status = objOwnerSet (so->so_timeoSem, fdObject); if (status == ERROR) { (void)bsdSockClose (so); return (ERROR); } status = objOwnerSet (so->so_rcv.sb_Sem, fdObject); if (status == ERROR) { (void)bsdSockClose (so); return (ERROR); } status = objOwnerSet (so->so_snd.sb_Sem, fdObject); if (status == ERROR) { (void)bsdSockClose (so); return (ERROR); }#endif /* _WRS_VXWORKS_5_X */ /* save fd in the socket structure */ so->so_fd = fd;#ifdef VIRTUAL_STACK /* set the vsid in the socket to the current stack */ if (setsockopt (fd, SOL_SOCKET, SO_VSID, (char *)&myStackNum, sizeof (myStackNum)) != OK) { (void)bsdSockClose (so); return (ERROR); }#endif /* VIRTUAL_STACK */ return (fd); }/********************************************************************************* bsdConnect - initiate a connection to a socket** If <s> is a socket of type SOCK_STREAM, this routine establishes a virtual* circuit between <s> and another socket specified by <name>. If <s> is of* type SOCK_DGRAM, it permanently specifies the peer to which messages* are sent. If <s> is of type SOCK_RAW, it specifies the raw socket upon* which data is to be sent and received. The <name> parameter specifies the* address of the other socket.** RETURNS* OK, or ERROR if the call fails.** NOMANUAL*/STATUS connect ( int s, /* socket descriptor */ struct sockaddr *name, /* addr of socket to connect */ int namelen /* length of name, in bytes */ ) { struct mbuf *nam; int slev; int status; FAST struct socket *so; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ /* * For non-blocking sockets, exit immediately if a previous connection * attempt is still pending. */ slev = splnet (); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { splx (slev); netErrnoSet (EALREADY); return (ERROR); } splx (slev); status = bsdSockargs (&nam, (caddr_t)name, namelen, MT_SONAME); if (status) { netErrnoSet (status); return (ERROR); }#if (CPU == SIMHPPA)/* * Set the size of the receive buffer. * This is the way (without rewriting the user app) to get * data from the master to auto-segment and fit in the pty. */{ int bLen = 660; status = setsockopt (s, SOL_SOCKET, SO_RCVBUF, &bLen, sizeof (bLen)); if (status == ERROR) return (ERROR);}#endif /* * Attempt to establish the connection. For TCP sockets, this routine * just begins the three-way handshake process. For all other sockets, * it succeeds or fails immediately. */ status = soconnect (so, nam); if (status) { /* * Fatal error: unable to record remote address or (TCP only) * couldn't send initial SYN segment. */ netErrnoSet (status); so->so_state &= ~SS_ISCONNECTING; m_freem(nam); return (ERROR); } /* * For non-blocking sockets, exit if the connection attempt is * still pending. This condition only occurs for TCP sockets if * no SYN reply arrives before the soconnect() routine completes. */ slev = splnet(); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { netErrnoSet (EINPROGRESS); splx (slev); m_freem (nam); return (ERROR); } /* * Wait until a pending connection completes or a timeout occurs. * This delay might occur for TCP sockets. Other socket types * "connect" or fail instantly. */ while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) ksleep (so->so_timeoSem); if (so->so_error) { /* Connection attempt failed immediately or (TCP only) timed out. */ status = ERROR; netErrnoSet ((int) so->so_error); so->so_error = 0; } else { /* Connection attempt succeeded. */ status = OK; } splx (slev); m_freem (nam); return (status); }/******************************************************************************** bsdConnectWithTimeout - attempt socket connection within a specified duration** This routine performs the same function as connect(); however, in addition,* users can specify how long to continue attempting the new connection. ** If the <timeVal> is a NULL pointer, this routine performs exactly like* connect(). If <timeVal> is not NULL, it will attempt to establish a new* connection for the duration of the time specified in <timeVal>, after* which it will report a time-out error if the connection is not* established.** RETURNS: OK, or ERROR if a connection cannot be established before timeout** SEE ALSO: connect()** NOMANUAL*/STATUS connectWithTimeout ( int sock, /* socket descriptor */ struct sockaddr *adrs, /* addr of the socket to connect */ int adrsLen, /* length of the socket, in bytes */ struct timeval *timeVal /* time-out value */ ) { int on = 0; fd_set writeFds; int retVal = ERROR; int error; int peerAdrsLen; struct sockaddr peerAdrs; struct socket *so; if (timeVal == NULL) return (connect (sock, adrs, adrsLen)); if ((so = (struct socket *) iosFdValue (sock)) == (struct socket *) ERROR) return (ERROR);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (sock) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ if (!(so->so_state & SS_NBIO)) { on = 1; /* set NBIO to have the connect() return without pending */ if ((ioctl (sock, FIONBIO, (int) &on)) == ERROR) return (ERROR); } if (connect (sock, adrs, adrsLen) < 0) { /* * When a TCP socket is set to non-blocking mode, the connect() * routine might return EINPROGRESS (if the three-way handshake * is not completed immediately) or EALREADY (if a previous connect * attempt is still pending). All other errors (for any socket type) * indicate a fatal problem, such as insufficient memory to record * the remote address or (for TCP) an inability to transmit the * initial SYN segment. */ error = errnoGet () & 0xffff; if (error == EINPROGRESS || error == EALREADY) { /* * Use the select() routine to monitor the socket status. The * socket will be writable when the three-way handshake completes * or when the handshake timeout occurs. */ FD_ZERO (&writeFds); FD_SET (sock, &writeFds); if (select (FD_SETSIZE, (fd_set *) NULL, &writeFds, (fd_set *) NULL, timeVal) > 0) { /* The FD_ISSET test is theoretically redundant, but safer. */ if (FD_ISSET (sock, &writeFds)) { /* * The connection attempt has completed. The getpeername() * routine retrieves the remote address if the three-way * handshake succeeded and fails if the attempt timed out. */ peerAdrsLen = sizeof (peerAdrs); if (getpeername (sock, &peerAdrs, &peerAdrsLen) != ERROR) retVal = OK; } } else netErrnoSet (ETIMEDOUT); } } else retVal = OK; if (on) { on = 0; /* turn OFF the non-blocking I/O */ if ((ioctl (sock, FIONBIO, (int) &on)) == ERROR) return (ERROR); } return (retVal); }/********************************************************************************* bsdSendto - send a message to a socket** This routine sends a message to the datagram socket named by <to>. The* socket <s> will be received by the receiver as the sending socket.* * The maximum length of <buf> is subject to the limits on UDP buffer* size; see the discussion of SO_SNDBUF in the setsockopt() manual* entry.** RETURNS* The number of bytes sent, or ERROR if the call fails.* * SEE ALSO* setsockopt()** NOMANUAL*/int sendto ( FAST int s, /* socket to send data to */ FAST caddr_t buf, /* pointer to data buffer */ FAST int bufLen, /* length of buffer */ FAST int flags, /* flags to underlying protocols */ FAST struct sockaddr *to, /* recipient's address */ FAST int tolen /* length of <to> sockaddr */ ) { FAST struct socket *so; FAST int spl; int status; struct mbuf *mto; int len; /* value/result */ struct uio usrIo; /* user IO structure */ struct iovec ioVec; /* IO vector structure */ struct mbuf * pMbuf = NULL; /* pointer to mbuf */ struct uio * pUsrIo = NULL; /* pointer to User IO structure */ /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) { if ((flags & MSG_MBUF) && (buf)) m_freem ((struct mbuf *)buf); return (ERROR); }#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ spl = splnet (); status = bsdSockargs (&mto, (char *) to, tolen, MT_SONAME); if (status) { netErrnoSet (status); if ((flags & MSG_MBUF) && (buf)) m_freem ((struct mbuf *)buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -