📄 bsdsocklib.c
字号:
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); }#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ 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 */#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (so->so_fd) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ 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);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (sd) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ /* 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); sendLen = len - auio.uio_resid; /* If status has been set to EINVAL in TCP, then TCP has freed the * mbufs. We do not free the mbufs, we return the errno * to the application. */ if (status == EINVAL) { netErrnoSet (status); splx (slev); if (mallocedIov) { FREE (pIovCopy, MT_DATA); } return (ERROR); } /* if status is not EINVAL, we free the mbufs as TCP has not freed it */ if (control) m_freem(control); if (to) m_freem(to); splx (slev); if (mallocedIov) { FREE (pIovCopy, MT_DATA); } if (status) { if (auio.uio_resid != len && (status == EINTR || status == EWOULDBLOCK)) status = OK; } return (status == OK ? sendLen : ERROR); }/********************************************************************************* bsdRecvfrom - receive a message from a socket** This routine receives a message from a datagram socket regardless of * whether it is connected. If <from> is non-zero, the address of the* sender's socket is copied to it. The value-result parameter <pFromLen>* should be initialized to the size of the <from> buffer. On return,* <pFromLen> contains the actual size of the address stored in <from>.* * The maximum length of <buf> is subject to the limits on UDP buffer* size; see the discussion of SO_RCVBUF in the setsockopt() manual* entry.* * RETURNS* The number of number of bytes received, or ERROR if the call fails.* * SEE ALSO* setsockopt()** NOMANUAL*/int recvfrom ( FAST int s, /* socket to receive from */ FAST char *buf, /* pointer to data buffer */ FAST int bufLen, /* length of buffer */ FAST int flags, /* flags to underlying protocols */ FAST struct sockaddr *from, /* where to copy sender's addr */ FAST int *pFromLen /* value/result length of <from> */ ) { FAST struct socket *so; FAST int spl; FAST int fromLen; int status; struct mbuf * mfrom; int len; /* value/result */ struct uio usrIo; /* user IO structure */ struct iovec ioVec; /* IO vector structure */ int soFlags; struct mbuf ** ppRcvMbuf = NULL; /* for zero copy interface */#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); 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_READ; ioVec.iov_base = (caddr_t) buf; ioVec.iov_len = bufLen; soFlags = flags; if (flags & MSG_MBUF) /* if zero copy interface enabled */ ppRcvMbuf = (struct mbuf **)buf; len = usrIo.uio_resid; status = soreceive (so, &mfrom, &usrIo, ppRcvMbuf, (struct mbuf **)0, &soFlags); if (from && pFromLen) { fromLen = *pFromLen; if (fromLen <= 0 || mfrom == NULL) fromLen = 0; else { if (fromLen > mfrom->m_len) fromLen = mfrom->m_len; bcopy ((char *) mtod (mfrom, char *), (char *) from, fromLen); } *pFromLen = fromLen; if (bsdSock43ApiFlag) { /* Convert the address structure contents to the BSD 4.3 format. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -