michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* OS/2 Sockets module michael@0: * michael@0: */ michael@0: michael@0: /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */ michael@0: /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */ michael@0: /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */ michael@0: /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */ michael@0: /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */ michael@0: michael@0: #include "primpl.h" michael@0: michael@0: #include /* For timeval. */ michael@0: michael@0: #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 michael@0: #define READ_FD 1 michael@0: #define WRITE_FD 2 michael@0: michael@0: /* --- SOCKET IO --------------------------------------------------------- */ michael@0: michael@0: michael@0: PRInt32 michael@0: _PR_MD_SOCKET(int domain, int type, int flags) michael@0: { michael@0: PRInt32 osfd, err; michael@0: michael@0: osfd = socket(domain, type, flags); michael@0: michael@0: if (osfd == -1) michael@0: { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_SOCKET_ERROR(err); michael@0: } michael@0: michael@0: return(osfd); michael@0: } michael@0: michael@0: /* michael@0: ** _MD_CloseSocket() -- Close a socket michael@0: ** michael@0: */ michael@0: PRInt32 michael@0: _MD_CloseSocket(PRInt32 osfd) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = soclose(osfd); michael@0: if (rv == -1) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_CLOSE_ERROR(err); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: PRInt32 michael@0: _MD_SocketAvailable(PRFileDesc *fd) michael@0: { michael@0: PRInt32 result; michael@0: michael@0: if (so_ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) { michael@0: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno()); michael@0: return -1; michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: static PRInt32 michael@0: socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout ) michael@0: { michael@0: PRInt32 rv = -1; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: PRIntervalTime epoch, now, elapsed, remaining; michael@0: PRBool wait_for_remaining; michael@0: PRInt32 syserror; michael@0: #ifdef BSD_SELECT michael@0: struct timeval tv; michael@0: fd_set rd_wr; michael@0: #else michael@0: int socks[1]; michael@0: long lTimeout; michael@0: #endif michael@0: michael@0: switch (timeout) { michael@0: case PR_INTERVAL_NO_WAIT: michael@0: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); michael@0: break; michael@0: case PR_INTERVAL_NO_TIMEOUT: michael@0: /* michael@0: * This is a special case of the 'default' case below. michael@0: * Please see the comments there. michael@0: */ michael@0: #ifdef BSD_SELECT michael@0: tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; michael@0: tv.tv_usec = 0; michael@0: FD_ZERO(&rd_wr); michael@0: do { michael@0: FD_SET(osfd, &rd_wr); michael@0: if (fd_type == READ_FD) michael@0: rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); michael@0: else michael@0: rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); michael@0: #else michael@0: lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; michael@0: do { michael@0: socks[0] = osfd; michael@0: if (fd_type == READ_FD) michael@0: rv = os2_select(socks, 1, 0, 0, lTimeout); michael@0: else michael@0: rv = os2_select(socks, 0, 1, 0, lTimeout); michael@0: #endif michael@0: if (rv == -1 && (syserror = sock_errno()) != EINTR) { michael@0: _PR_MD_MAP_SELECT_ERROR(syserror); michael@0: break; michael@0: } michael@0: if (_PR_PENDING_INTERRUPT(me)) { michael@0: me->flags &= ~_PR_INTERRUPT; michael@0: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); michael@0: rv = -1; michael@0: break; michael@0: } michael@0: } while (rv == 0 || (rv == -1 && syserror == EINTR)); michael@0: break; michael@0: default: michael@0: now = epoch = PR_IntervalNow(); michael@0: remaining = timeout; michael@0: #ifdef BSD_SELECT michael@0: FD_ZERO(&rd_wr); michael@0: #endif michael@0: do { michael@0: /* michael@0: * We block in select for at most michael@0: * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, michael@0: * so that there is an upper limit on the delay michael@0: * before the interrupt bit is checked. michael@0: */ michael@0: #ifdef BSD_SELECT michael@0: wait_for_remaining = PR_TRUE; michael@0: tv.tv_sec = PR_IntervalToSeconds(remaining); michael@0: if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { michael@0: wait_for_remaining = PR_FALSE; michael@0: tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; michael@0: tv.tv_usec = 0; michael@0: } else { michael@0: tv.tv_usec = PR_IntervalToMicroseconds( michael@0: remaining - michael@0: PR_SecondsToInterval(tv.tv_sec)); michael@0: } michael@0: FD_SET(osfd, &rd_wr); michael@0: if (fd_type == READ_FD) michael@0: rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); michael@0: else michael@0: rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); michael@0: #else michael@0: wait_for_remaining = PR_TRUE; michael@0: lTimeout = PR_IntervalToMilliseconds(remaining); michael@0: if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { michael@0: wait_for_remaining = PR_FALSE; michael@0: lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; michael@0: } michael@0: socks[0] = osfd; michael@0: if (fd_type == READ_FD) michael@0: rv = os2_select(socks, 1, 0, 0, lTimeout); michael@0: else michael@0: rv = os2_select(socks, 0, 1, 0, lTimeout); michael@0: #endif michael@0: /* michael@0: * we don't consider EINTR a real error michael@0: */ michael@0: if (rv == -1 && (syserror = sock_errno()) != EINTR) { michael@0: _PR_MD_MAP_SELECT_ERROR(syserror); michael@0: break; michael@0: } michael@0: if (_PR_PENDING_INTERRUPT(me)) { michael@0: me->flags &= ~_PR_INTERRUPT; michael@0: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); michael@0: rv = -1; michael@0: break; michael@0: } michael@0: /* michael@0: * We loop again if select timed out or got interrupted michael@0: * by a signal, and the timeout deadline has not passed yet. michael@0: */ michael@0: if (rv == 0 || (rv == -1 && syserror == EINTR)) { michael@0: /* michael@0: * If select timed out, we know how much time michael@0: * we spent in blocking, so we can avoid a michael@0: * PR_IntervalNow() call. michael@0: */ michael@0: if (rv == 0) { michael@0: if (wait_for_remaining) { michael@0: now += remaining; michael@0: } else { michael@0: #ifdef BSD_SELECT michael@0: now += PR_SecondsToInterval(tv.tv_sec) michael@0: + PR_MicrosecondsToInterval(tv.tv_usec); michael@0: #else michael@0: now += PR_MillisecondsToInterval(lTimeout); michael@0: #endif michael@0: } michael@0: } else { michael@0: now = PR_IntervalNow(); michael@0: } michael@0: elapsed = (PRIntervalTime) (now - epoch); michael@0: if (elapsed >= timeout) { michael@0: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); michael@0: rv = -1; michael@0: break; michael@0: } else { michael@0: remaining = timeout - elapsed; michael@0: } michael@0: } michael@0: } while (rv == 0 || (rv == -1 && syserror == EINTR)); michael@0: break; michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _MD_Accept(PRFileDesc *fd, PRNetAddr *addr, michael@0: PRUint32 *addrlen, PRIntervalTime timeout) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: michael@0: while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1) michael@0: { michael@0: err = sock_errno(); michael@0: if ((err == EWOULDBLOCK) || (err == ECONNABORTED)) michael@0: { michael@0: if (fd->secret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_ACCEPT_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, michael@0: PRIntervalTime timeout) michael@0: { michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect michael@0: * modifies the sockaddr structure. michael@0: * See Bugzilla bug 100776. */ michael@0: michael@0: /* michael@0: * We initiate the connection setup by making a nonblocking connect() michael@0: * call. If the connect() call fails, there are two cases we handle michael@0: * specially: michael@0: * 1. The connect() call was interrupted by a signal. In this case michael@0: * we simply retry connect(). michael@0: * 2. The NSPR socket is nonblocking and connect() fails with michael@0: * EINPROGRESS. We first wait until the socket becomes writable. michael@0: * Then we try to find out whether the connection setup succeeded michael@0: * or failed. michael@0: */ michael@0: michael@0: retry: michael@0: if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) michael@0: { michael@0: err = sock_errno(); michael@0: michael@0: if (err == EINTR) { michael@0: if (_PR_PENDING_INTERRUPT(me)) { michael@0: me->flags &= ~_PR_INTERRUPT; michael@0: PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); michael@0: return -1; michael@0: } michael@0: goto retry; michael@0: } michael@0: michael@0: if (!fd->secret->nonblocking && (err == EINPROGRESS)) michael@0: { michael@0: /* michael@0: * socket_io_wait() may return -1 or 1. michael@0: */ michael@0: michael@0: rv = socket_io_wait(osfd, WRITE_FD, timeout); michael@0: if (rv == -1) { michael@0: return -1; michael@0: } michael@0: michael@0: PR_ASSERT(rv == 1); michael@0: if (_PR_PENDING_INTERRUPT(me)) { michael@0: me->flags &= ~_PR_INTERRUPT; michael@0: PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); michael@0: return -1; michael@0: } michael@0: err = _MD_os2_get_nonblocking_connect_error(osfd); michael@0: if (err != 0) { michael@0: _PR_MD_MAP_CONNECT_ERROR(err); michael@0: return -1; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: _PR_MD_MAP_CONNECT_ERROR(err); michael@0: } michael@0: michael@0: return rv; michael@0: } /* _MD_connect */ michael@0: michael@0: PRInt32 michael@0: _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) michael@0: { michael@0: PRInt32 rv, err; michael@0: rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_BIND_ERROR(err); michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: michael@0: PRInt32 michael@0: _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) michael@0: { michael@0: PRInt32 rv, err; michael@0: rv = listen(fd->secret->md.osfd, backlog); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_DEFAULT_ERROR(err); michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: michael@0: PRInt32 michael@0: _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, michael@0: PRIntervalTime timeout) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: michael@0: while ((rv = recv(osfd,buf,amount,flags)) == -1) michael@0: { michael@0: err = sock_errno(); michael@0: if ((err == EWOULDBLOCK)) { michael@0: if (fd->secret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_RECV_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, michael@0: PRIntervalTime timeout) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: michael@0: while ((rv = send(osfd,buf,amount,flags)) == -1) michael@0: { michael@0: err = sock_errno(); michael@0: if ((err == EWOULDBLOCK)) { michael@0: if (fd->secret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * optimization; if bytes sent is less than "amount" call michael@0: * select before returning. This is because it is likely that michael@0: * the next send() call will return EWOULDBLOCK. michael@0: */ michael@0: if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) michael@0: && (timeout != PR_INTERVAL_NO_WAIT)) michael@0: { michael@0: if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { michael@0: rv = -1; michael@0: goto done; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_SEND_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, michael@0: const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: while ((rv = sendto(osfd, buf, amount, flags, michael@0: (struct sockaddr *) addr, addrlen)) == -1) michael@0: { michael@0: err = sock_errno(); michael@0: if ((err == EWOULDBLOCK)) michael@0: { michael@0: if (fd->secret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_SENDTO_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, michael@0: PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: michael@0: while( (*addrlen = PR_NETADDR_SIZE(addr)), michael@0: ((rv = recvfrom(osfd, buf, amount, flags, michael@0: (struct sockaddr *) addr, (int *)addrlen)) == -1)) michael@0: { michael@0: err = sock_errno(); michael@0: if ((err == EWOULDBLOCK)) { michael@0: if (fd->secret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_RECVFROM_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, michael@0: PRIntervalTime timeout) michael@0: { michael@0: PRInt32 rv, err; michael@0: PRThread *me = _PR_MD_CURRENT_THREAD(); michael@0: PRInt32 index, amount = 0; michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: struct iovec osiov[PR_MAX_IOVECTOR_SIZE]; michael@0: michael@0: /* Ensured by PR_Writev */ michael@0: PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE); michael@0: michael@0: /* michael@0: * We can't pass iov to so_writev because PRIOVec and struct iovec michael@0: * may not be binary compatible. Make osiov a copy of iov and michael@0: * pass osiov to so_writev . michael@0: */ michael@0: for (index = 0; index < iov_size; index++) { michael@0: osiov[index].iov_base = iov[index].iov_base; michael@0: osiov[index].iov_len = iov[index].iov_len; michael@0: } michael@0: michael@0: /* michael@0: * Calculate the total number of bytes to be sent; needed for michael@0: * optimization later. michael@0: * We could avoid this if this number was passed in; but it is michael@0: * probably not a big deal because iov_size is usually small (less than michael@0: * 3) michael@0: */ michael@0: if (!fd->secret->nonblocking) { michael@0: for (index=0; indexsecret->nonblocking) { michael@0: break; michael@0: } michael@0: if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) michael@0: goto done; michael@0: } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ michael@0: continue; michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * optimization; if bytes sent is less than "amount" call michael@0: * select before returning. This is because it is likely that michael@0: * the next writev() call will return EWOULDBLOCK. michael@0: */ michael@0: if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) michael@0: && (timeout != PR_INTERVAL_NO_WAIT)) { michael@0: if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { michael@0: rv = -1; michael@0: goto done; michael@0: } michael@0: } michael@0: if (rv < 0) { michael@0: _PR_MD_MAP_WRITEV_ERROR(err); michael@0: } michael@0: done: michael@0: return(rv); michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) michael@0: { michael@0: PRInt32 rv; michael@0: michael@0: rv = shutdown(fd->secret->md.osfd, how); michael@0: if (rv < 0) michael@0: _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno()); michael@0: return rv; michael@0: } michael@0: michael@0: PRInt32 michael@0: _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = socketpair(af, type, flags, osfd); michael@0: if (rv < 0) { michael@0: err = _MD_ERRNO(); michael@0: _PR_MD_MAP_SOCKETPAIR_ERROR(err); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: PRStatus michael@0: _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = getsockname(fd->secret->md.osfd, michael@0: (struct sockaddr *) addr, (int *)addrlen); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_GETSOCKNAME_ERROR(err); michael@0: } michael@0: return rv==0?PR_SUCCESS:PR_FAILURE; michael@0: } michael@0: michael@0: PRStatus michael@0: _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = getpeername(fd->secret->md.osfd, michael@0: (struct sockaddr *) addr, (int *)addrlen); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_GETPEERNAME_ERROR(err); michael@0: } michael@0: return rv==0?PR_SUCCESS:PR_FAILURE; michael@0: } michael@0: michael@0: PRStatus michael@0: _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, michael@0: char* optval, PRInt32* optlen) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_GETSOCKOPT_ERROR(err); michael@0: } michael@0: return rv==0?PR_SUCCESS:PR_FAILURE; michael@0: } michael@0: michael@0: PRStatus michael@0: _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, michael@0: const char* optval, PRInt32 optlen) michael@0: { michael@0: PRInt32 rv, err; michael@0: michael@0: rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); michael@0: if (rv < 0) { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_SETSOCKOPT_ERROR(err); michael@0: } michael@0: return rv==0?PR_SUCCESS:PR_FAILURE; michael@0: } michael@0: michael@0: void michael@0: _MD_MakeNonblock(PRFileDesc *fd) michael@0: { michael@0: PRInt32 osfd = fd->secret->md.osfd; michael@0: PRInt32 err; michael@0: PRUint32 one = 1; michael@0: michael@0: if (osfd <= 2) { michael@0: /* Don't mess around with stdin, stdout or stderr */ michael@0: return; michael@0: } michael@0: michael@0: err = so_ioctl( osfd, FIONBIO, (char *) &one, sizeof(one)); michael@0: if ( err != 0 ) michael@0: { michael@0: err = sock_errno(); michael@0: _PR_MD_MAP_SOCKET_ERROR(err); michael@0: } michael@0: }