📄 unix.c
字号:
* On pre-2.6 Solaris, send() is much slower than write(). * On 2.6 and beyond, with in-kernel sockets, send() and * write() are fairly equivalent in performance. */#if defined(SOLARIS) PR_ASSERT(0 == flags); while ((rv = write(osfd,buf,tmp_amount)) == -1) {#else while ((rv = send(osfd,buf,amount,flags)) == -1) {#endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else {#if defined(SOLARIS) /* * The write system call has been reported to return the ERANGE * error on occasion. Try to write in smaller chunks to workaround * this bug. */ if (err == ERANGE) { if (tmp_amount > 1) { tmp_amount = tmp_amount/2; /* half the bytes */ continue; } }#endif break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next send() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (_PR_IS_NATIVE_THREAD(me)) { if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { rv = -1; goto done; } } else { if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { rv = -1; goto done; } } } if (rv < 0) { _PR_MD_MAP_SEND_ERROR(err); }done: return(rv);}PRInt32 _MD_sendto( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout){ PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD();#ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) &addrCopy, addrlen)) == -1) {#else while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) addr, addrlen)) == -1) {#endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_SENDTO_ERROR(err); }done: return(rv);}PRInt32 _MD_writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout){ PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 index, amount = 0; PRInt32 osfd = fd->secret->md.osfd; /* * Calculate the total number of bytes to be sent; needed for * optimization later. * We could avoid this if this number was passed in; but it is * probably not a big deal because iov_size is usually small (less than * 3) */ if (!fd->secret->nonblocking) { for (index=0; index<iov_size; index++) { amount += iov[index].iov_len; } } while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next writev() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (_PR_IS_NATIVE_THREAD(me)) { if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { rv = -1; goto done; } } else { if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { rv = -1; goto done; } } } if (rv < 0) { _PR_MD_MAP_WRITEV_ERROR(err); }done: return(rv);}PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout){ PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = accept(osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_ACCEPT_ERROR(err); }done:#ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } }#endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv);}extern int _connect (int s, const struct sockaddr *name, int namelen);PRInt32 _MD_connect( PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout){ PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 osfd = fd->secret->md.osfd;#ifdef IRIXextern PRInt32 _MD_irix_connect( PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);#endif#ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;#endif /* * We initiate the connection setup by making a nonblocking connect() * call. If the connect() call fails, there are two cases we handle * specially: * 1. The connect() call was interrupted by a signal. In this case * we simply retry connect(). * 2. The NSPR socket is nonblocking and connect() fails with * EINPROGRESS. We first wait until the socket becomes writable. * Then we try to find out whether the connection setup succeeded * or failed. */retry:#ifdef IRIX if ((rv = _MD_irix_connect(osfd, addr, addrlen, timeout)) == -1) {#else#ifdef _PR_HAVE_SOCKADDR_LEN if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {#else if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {#endif#endif err = _MD_ERRNO(); if (err == EINTR) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } goto retry; } if (!fd->secret->nonblocking && (err == EINPROGRESS)) { if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) return -1; } else { /* * socket_io_wait() may return -1 or 1. */ rv = socket_io_wait(osfd, WRITE_FD, timeout); if (rv == -1) { return -1; } } PR_ASSERT(rv == 1); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } err = _MD_unix_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return -1; } return 0; } _PR_MD_MAP_CONNECT_ERROR(err); } return rv;} /* _MD_connect */PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen){ PRInt32 rv, err;#ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);#else rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);#endif if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_BIND_ERROR(err); } return(rv);}PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog){ PRInt32 rv, err; rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_LISTEN_ERROR(err); } return(rv);}PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how){ PRInt32 rv, err; rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SHUTDOWN_ERROR(err); } return(rv);}PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32 *osfd){ PRInt32 rv, err; rv = socketpair(af, type, flags, osfd); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKETPAIR_ERROR(err); } return rv;}PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen){ PRInt32 rv, err; rv = getsockname(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);#ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } }#endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE;}PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen){ PRInt32 rv, err; rv = getpeername(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);#ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } }#endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETPEERNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE;}PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen){ PRInt32 rv, err; rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE;}PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen){ PRInt32 rv, err; rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE;}PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable){ int rv; rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -