📄 bsdsocklib.c
字号:
#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 status = soconnect (so, nam); if (status) { netErrnoSet (status); so->so_state &= ~SS_ISCONNECTING; m_freem(nam); return (ERROR); } slev = splnet(); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { netErrnoSet (EINPROGRESS); splx (slev); so->so_state &= ~SS_ISCONNECTING; m_freem (nam); return (ERROR); } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) ksleep (&so->so_timeoSem); if (so->so_error) { netErrnoSet ((int) so->so_error); so->so_error = 0; splx (slev); so->so_state &= ~SS_ISCONNECTING; m_freem (nam); return (ERROR); } splx (slev); so->so_state &= ~SS_ISCONNECTING; m_freem (nam); return (OK); }/******************************************************************************** bsdConnectWithTimeout - attempt a connection over a socket for 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.** 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 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); 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 socket is set to non-blocking mode, connect() will return * with EINPROGRESS if a connection cannot be setup immediately. */ if ((errnoGet () & 0xffff) == EINPROGRESS) { /* We do synchronous polling on the write side of this socket * using select() with the given <timeVal> timeout value until * the connection gets established. */ FD_ZERO (&writeFds); FD_SET (sock, &writeFds); /* poll write-side of <sock> */ if (select (FD_SETSIZE, (fd_set *) NULL, &writeFds, (fd_set *) NULL, timeVal) > 0) { /* select() is successful, see if our socket is actually * selected for writing. */ if (FD_ISSET (sock, &writeFds)) { /* connection attempt has completed. we now see if * it was a successful attempt by trying to get the * remote peer's address. If getpeername() succeeds * we have a connection, otherwise the connect() has * failed. */ 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); } spl = splnet (); status = bsdSockargs (&mto, (char *) to, tolen, MT_SONAME); if (status) { netErrnoSet (status); if ((flags & MSG_MBUF) && (buf)) m_freem ((struct mbuf *)buf); splx (spl); return (ERROR); } if (flags & MSG_MBUF) { pMbuf = (struct mbuf *) buf; len = bufLen; } else { usrIo.uio_iov = &ioVec; usrIo.uio_iovcnt = 1; usrIo.uio_offset = 0; usrIo.uio_resid = bufLen; usrIo.uio_segflg = UIO_USERSPACE; usrIo.uio_rw = UIO_WRITE; ioVec.iov_base = (caddr_t) buf; ioVec.iov_len = bufLen; pUsrIo = &usrIo; len = usrIo.uio_resid; } status = sosend (so, mto, pUsrIo, pMbuf, 0, flags); m_free (mto); splx (spl); if (status) { if (pUsrIo != NULL && pUsrIo->uio_resid != len && (status == EINTR || status == EWOULDBLOCK)) status = OK; } return (status == OK ? ((pUsrIo == NULL) ? len : (len - pUsrIo->uio_resid)) : ERROR); }/********************************************************************************* bsdSend - send data to a socket** This routine transmits data to a previously established connection-based* (stream) socket.** The maximum length of <buf> is subject to the limits* on TCP 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 send ( FAST int s, /* socket to send to */ FAST char *buf, /* pointer to buffer to transmit */ FAST int bufLen, /* length of buffer */ FAST int flags /* flags to underlying protocols */ ) { FAST struct socket *so; FAST int status; FAST int spl; 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); } spl = splnet (); if (flags & MSG_MBUF) { pMbuf = (struct mbuf *) buf; len = bufLen; } else { usrIo.uio_iov = &ioVec; usrIo.uio_iovcnt = 1; usrIo.uio_offset = 0; usrIo.uio_resid = bufLen; usrIo.uio_segflg = UIO_USERSPACE; usrIo.uio_rw = UIO_WRITE; ioVec.iov_base = (caddr_t) buf; ioVec.iov_len = bufLen; pUsrIo = &usrIo; len = usrIo.uio_resid; } status = sosend (so, (struct mbuf *) NULL, pUsrIo, pMbuf, (struct mbuf *)NULL, flags); splx (spl); if (status) { if (pUsrIo != NULL && pUsrIo->uio_resid != len && (status == EINTR || status == EWOULDBLOCK)) status = OK; } return (status == OK ? ((pUsrIo == NULL) ? len : (len - pUsrIo->uio_resid)) : ERROR); }/********************************************************************************* bsdSockWrite - write to a socket** This routine is called by the I/O system when a write is done on a socket.*/LOCAL int bsdSockWrite ( FAST struct socket *so, FAST char *buf, FAST int bufLen ) { FAST int status; FAST int spl; int len; /* value/result */ struct uio usrIo; /* user IO structure */ struct iovec ioVec; /* IO vector structure */ spl = splnet (); usrIo.uio_iov = &ioVec; usrIo.uio_iovcnt = 1; usrIo.uio_offset = 0; usrIo.uio_resid = bufLen; usrIo.uio_segflg = UIO_USERSPACE; usrIo.uio_rw = UIO_WRITE; ioVec.iov_base = (caddr_t) buf; ioVec.iov_len = bufLen; len = usrIo.uio_resid; status = sosend (so, (struct mbuf *) NULL, &usrIo, (struct mbuf *)0, (struct mbuf *)NULL, 0); splx (spl); if (status) { if (usrIo.uio_resid != len && (status == EINTR || status == EWOULDBLOCK)) status = OK; } return (status == OK ? (len - usrIo.uio_resid) : ERROR); }/********************************************************************************* bsdSendmsg - send a message to a socket** This routine sends a message to a datagram socket. It may be used in * place of sendto() to decrease the overhead of reconstructing the * message-header structure (`msghdr') for each message.* * RETURNS* The number of bytes sent, or ERROR if the call fails.** NOMANUAL*/int sendmsg ( int sd, /* socket to send to */ struct msghdr *mp, /* scatter-gather message header */ int flags /* flags to underlying protocols */ ) { FAST struct iovec *iov; FAST struct iovec * pIovCopy; /* kernel copy of user iov */ FAST int ix; struct socket *so; struct uio auio; struct iovec aiov [UIO_SMALLIOV]; /* use stack for small user iov */ struct mbuf *to; struct mbuf *control; int len; int status; int slev; BOOL mallocedIov; /* TRUE if kernel iov copy malloced */ /* from system pool */ int sendLen; /* length of sent message */ if (flags & MSG_MBUF) { netErrnoSet (EINVAL); return (ERROR); /* mbuf uio not supported */ } /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (sd)) == (struct socket *) ERROR) return (ERROR); /* allocate space to copy user struct iovec */ if (mp->msg_iovlen >= UIO_SMALLIOV) { if (mp->msg_iovlen >= UIO_MAXIOV) { netErrnoSet (EMSGSIZE); return (ERROR); } MALLOC (pIovCopy, struct iovec *, sizeof (struct iovec) * mp->msg_iovlen, MT_DATA, M_WAIT); if (pIovCopy == NULL) { netErrnoSet (ENOBUFS); return (ERROR); } mallocedIov = TRUE; } else { pIovCopy = aiov; mallocedIov = FALSE; } slev = splnet (); auio.uio_iov = pIovCopy; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_offset = 0; auio.uio_rw = UIO_WRITE; auio.uio_resid = 0; iov = mp->msg_iov; for (ix = 0; ix < mp->msg_iovlen; ix++, iov++) { if (iov->iov_len < 0) { netErrnoSet (EINVAL); splx (slev); if (mallocedIov) { FREE (auio.uio_iov, MT_IOV); } return (ERROR); } if (iov->iov_len == 0) continue; pIovCopy->iov_len = iov->iov_len; pIovCopy->iov_base = iov->iov_base; pIovCopy++; auio.uio_resid += iov->iov_len; } /* Save a pointer to struct iovec copy */ pIovCopy = auio.uio_iov; if (mp->msg_name) { status = bsdSockargs (&to, mp->msg_name, mp->msg_namelen, MT_SONAME); if (status) { netErrnoSet (status); splx (slev); if (mallocedIov) { FREE (pIovCopy, MT_DATA); } return (ERROR); } } else to = 0; if (mp->msg_control) { status = bsdSockargs (&control, mp->msg_control, mp->msg_controllen, MT_CONTROL); if (status) { if (to) m_freem(to); netErrnoSet (status); splx (slev); if (mallocedIov) { FREE (pIovCopy, MT_DATA); } return (ERROR); } } else control = 0; len = auio.uio_resid; status = sosend (so, to, &auio, (struct mbuf *)0, control, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -