summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2002-01-22 21:57:42 +0000
committerwtc%netscape.com <devnull@localhost>2002-01-22 21:57:42 +0000
commit60337c066e1a88545f04efb2e55f18d320c79cb0 (patch)
treeaa8447fdcd1772c7891ddea02c51a01acfa4b532
parentb5907e7dcb74c70fe2aa413cc6bec773b93a917c (diff)
downloadnspr-hg-60337c066e1a88545f04efb2e55f18d320c79cb0.tar.gz
Bugzilla bug 100776: Merged the fix onto the NSPRPUB_PRE_4_2_CLIENT_BRANCH.
Modified files: configure configure.in _os2.h _os2_errors.h prsocket.c os2_errors.c os2poll.c os2sock.c
-rwxr-xr-xconfigure10
-rw-r--r--configure.in2
-rw-r--r--pr/include/md/_os2.h2
-rw-r--r--pr/include/md/_os2_errors.h7
-rw-r--r--pr/src/io/prsocket.c17
-rw-r--r--pr/src/md/os2/os2_errors.c125
-rw-r--r--pr/src/md/os2/os2poll.c266
-rw-r--r--pr/src/md/os2/os2sock.c1001
8 files changed, 657 insertions, 773 deletions
diff --git a/configure b/configure
index c3d0706e..59bad369 100755
--- a/configure
+++ b/configure
@@ -4541,10 +4541,6 @@ EOF
EOF
cat >> confdefs.h <<\EOF
-#define BSD_SELECT 1
-EOF
-
- cat >> confdefs.h <<\EOF
#define XP_PC 1
EOF
@@ -4571,6 +4567,10 @@ EOF
EOF
cat >> confdefs.h <<\EOF
+#define BSD_SELECT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
#define OS2 1
EOF
@@ -5573,7 +5573,7 @@ s%\[%\\&%g
s%\]%\\&%g
s%\$%$$%g
EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' ' | tr '\015' ' '`
rm -f conftest.defs
diff --git a/configure.in b/configure.in
index 32da0f4c..978c6266 100644
--- a/configure.in
+++ b/configure.in
@@ -1674,7 +1674,6 @@ mips-sony-newsos*)
*-os2*)
AC_DEFINE(XP_OS2)
- AC_DEFINE(BSD_SELECT)
AC_DEFINE(XP_PC)
AC_DEFINE(_PR_GLOBAL_THREADS_ONLY)
OBJ_SUFFIX=obj
@@ -1692,6 +1691,7 @@ mips-sony-newsos*)
# EMX/GCC build
if test "$GNU_CC"; then
AC_DEFINE(XP_OS2_EMX)
+ AC_DEFINE(BSD_SELECT)
AC_DEFINE(OS2)
AR=emxomfar
AR_FLAGS='-p256 r $@'
diff --git a/pr/include/md/_os2.h b/pr/include/md/_os2.h
index d98262d1..9f2e6dcf 100644
--- a/pr/include/md/_os2.h
+++ b/pr/include/md/_os2.h
@@ -537,4 +537,6 @@ unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long fla
#define FreeLibrary(x) DosFreeModule((HMODULE)x)
#define OutputDebugString(x)
+extern int _MD_os2_get_nonblocking_connect_error(int osfd);
+
#endif /* nspr_os2_defs_h___ */
diff --git a/pr/include/md/_os2_errors.h b/pr/include/md/_os2_errors.h
index f77e8f6e..6f742be8 100644
--- a/pr/include/md/_os2_errors.h
+++ b/pr/include/md/_os2_errors.h
@@ -46,8 +46,8 @@ NSPR_API(void) _MD_os2_map_opendir_error(PRInt32 err);
NSPR_API(void) _MD_os2_map_closedir_error(PRInt32 err);
#define _PR_MD_MAP_CLOSEDIR_ERROR _MD_os2_map_closedir_error
-NSPR_API(void) _MD_unix_readdir_error(PRInt32 err);
-#define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error
+NSPR_API(void) _MD_os2_readdir_error(PRInt32 err);
+#define _PR_MD_MAP_READDIR_ERROR _MD_os2_readdir_error
NSPR_API(void) _MD_os2_map_delete_error(PRInt32 err);
#define _PR_MD_MAP_DELETE_ERROR _MD_os2_map_delete_error
@@ -103,6 +103,9 @@ NSPR_API(void) _MD_os2_map_send_error(PRInt32 err);
NSPR_API(void) _MD_os2_map_sendto_error(PRInt32 err);
#define _PR_MD_MAP_SENDTO_ERROR _MD_os2_map_sendto_error
+NSPR_API(void) _MD_os2_map_writev_error(int err);
+#define _PR_MD_MAP_WRITEV_ERROR _MD_os2_map_writev_error
+
NSPR_API(void) _MD_os2_map_accept_error(PRInt32 err);
#define _PR_MD_MAP_ACCEPT_ERROR _MD_os2_map_accept_error
diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c
index e6eacaa1..217b6fd0 100644
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -338,22 +338,11 @@ static PRStatus PR_CALLBACK SocketConnectContinue(
#elif defined(XP_OS2)
- if (out_flags & PR_POLL_EXCEPT) {
- int len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len)
- < 0) {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
- }
- if (err != 0) {
- _PR_MD_MAP_CONNECT_ERROR(err);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- }
+ err = _MD_os2_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
return PR_FAILURE;
}
-
- PR_ASSERT(out_flags & PR_POLL_WRITE);
return PR_SUCCESS;
#elif defined(XP_MAC)
diff --git a/pr/src/md/os2/os2_errors.c b/pr/src/md/os2/os2_errors.c
index f5be8391..5efd2c16 100644
--- a/pr/src/md/os2/os2_errors.c
+++ b/pr/src/md/os2/os2_errors.c
@@ -35,6 +35,44 @@
#include "prerror.h"
#include "primpl.h"
+void _MD_os2_map_default_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EMSGSIZE:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
void _MD_os2_map_opendir_error(PRInt32 err)
{
switch (err) {
@@ -92,7 +130,7 @@ void _MD_os2_map_closedir_error(PRInt32 err)
}
}
-void _MD_unix_readdir_error(PRInt32 err)
+void _MD_os2_readdir_error(PRInt32 err)
{
switch (err) {
@@ -671,73 +709,17 @@ void _MD_os2_map_send_error(PRInt32 err)
void _MD_os2_map_sendto_error(PRInt32 err)
{
- switch (err) {
- case EWOULDBLOCK:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case ENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case EMSGSIZE:
- case EINVAL:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
- break;
- case ENOBUFS:
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
- break;
- case ECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case EISCONN:
- PR_SetError(PR_IS_CONNECTED_ERROR, err);
- break;
-#ifdef SOCEFAULT
- case SOCEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
-#endif
- case ERROR_NETNAME_DELETED:
- PR_SetError(PR_CONNECT_RESET_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
+ _MD_os2_map_default_error(err);
+}
+
+void _MD_os2_map_writev_error(int err)
+{
+ _MD_os2_map_default_error(err);
}
void _MD_os2_map_accept_error(PRInt32 err)
{
- switch (err) {
- case EWOULDBLOCK:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case ENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case EOPNOTSUPP:
- PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
- break;
-#ifdef SOCEFAULT
- case SOCEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
-#endif
- case EMFILE:
- PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
- break;
- case ENOBUFS:
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
+ _MD_os2_map_default_error(err);
}
void _MD_os2_map_acceptex_error(PRInt32 err)
@@ -759,6 +741,21 @@ void _MD_os2_map_acceptex_error(PRInt32 err)
}
}
+/*
+ * An error code of 0 means that the nonblocking connect succeeded.
+ */
+
+int _MD_os2_get_nonblocking_connect_error(int osfd)
+{
+ int err;
+ int len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == -1) {
+ return sock_errno();
+ } else {
+ return err;
+ }
+}
+
void _MD_os2_map_connect_error(PRInt32 err)
{
switch (err) {
diff --git a/pr/src/md/os2/os2poll.c b/pr/src/md/os2/os2poll.c
index 12f199f6..da477b1b 100644
--- a/pr/src/md/os2/os2poll.c
+++ b/pr/src/md/os2/os2poll.c
@@ -37,54 +37,64 @@
*/
#ifdef XP_OS2_EMX
- #include <sys/time.h> /* For timeval. */
+ #include <sys/time.h> /* For timeval. */
#endif
#include "primpl.h"
-PRInt32 _PR_MD_PR_POLL(
- PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+#ifndef BSD_SELECT
+/* Utility functions called when using OS/2 select */
+
+PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
+{
+ int i;
+ PRBool isSet = PR_FALSE;
+
+ for( i = start; i < start+count; i++ )
+ {
+ if( socks[i] == osfd )
+ isSet = PR_TRUE;
+ }
+
+ return isSet;
+}
+#endif
+
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
- PRInt32 osfd;
- int maxfd = -1;
+#ifdef BSD_SELECT
fd_set rd, wt, ex;
+#else
+ int rd, wt, ex;
+ int* socks;
+ unsigned long msecs;
+ int i, j;
+#endif
PRFileDesc *bottom;
PRPollDesc *pd, *epd;
- PRInt32 ready, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- struct timeval tv, *tvp = NULL;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
- /*
- * For restarting _MD_SELECT() if it is interrupted by a signal.
- * We use these variables to figure out how much time has elapsed
- * and how much of the timeout still remains.
- */
- PRIntervalTime start, elapsed, remaining;
+#ifdef BSD_SELECT
+ struct timeval tv, *tvp = NULL;
- if (_PR_PENDING_INTERRUPT(me))
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+#else
+ rd = 0;
+ wt = 0;
+ ex = 0;
+ socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
+
+ if (!socks)
{
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return -1;
}
+#endif
- /*
- ** Is it an empty set? If so, just sleep for the timeout and return
- */
- if (0 == npds)
- {
- PR_Sleep(timeout);
- return 0;
- }
-
- remaining = timeout;
- start = PR_IntervalNow();
-
- FD_ZERO(&rd);
- FD_ZERO(&wt);
- FD_ZERO(&ex);
-
- ready = 0;
+ ready = 0;
for (pd = pds, epd = pd + npds; pd < epd; pd++)
{
PRInt16 in_flags_read = 0, in_flags_write = 0;
@@ -95,19 +105,17 @@ PRInt32 _PR_MD_PR_POLL(
if (pd->in_flags & PR_POLL_READ)
{
in_flags_read = (pd->fd->methods->poll)(
- pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE),
- &out_flags_read);
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
}
if (pd->in_flags & PR_POLL_WRITE)
{
in_flags_write = (pd->fd->methods->poll)(
- pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ),
- &out_flags_write);
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
}
- if ((0 != (in_flags_read & out_flags_read))
- || (0 != (in_flags_write & out_flags_write)))
+ if ((0 != (in_flags_read & out_flags_read)) ||
+ (0 != (in_flags_write & out_flags_write)))
{
- /* this one's ready right now (buffered input) */
+ /* this one's ready right now */
if (0 == ready)
{
/*
@@ -128,37 +136,67 @@ PRInt32 _PR_MD_PR_POLL(
else
{
pd->out_flags = 0; /* pre-condition */
+
/* make sure this is an NSPR supported stack */
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottom); /* what to do about that? */
- if ((NULL != bottom)
- && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ if ((NULL != bottom) &&
+ (_PR_FILEDESC_OPEN == bottom->secret->state))
{
if (0 == ready)
{
- osfd = bottom->secret->md.osfd;
- if (osfd > maxfd) maxfd = osfd;
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd)
+ maxfd = osfd;
if (in_flags_read & PR_POLL_READ)
{
pd->out_flags |= _PR_POLL_READ_SYS_READ;
+#ifdef BSD_SELECT
FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
}
if (in_flags_read & PR_POLL_WRITE)
{
pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+#ifdef BSD_SELECT
FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
}
if (in_flags_write & PR_POLL_READ)
{
pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+#ifdef BSD_SELECT
FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
}
if (in_flags_write & PR_POLL_WRITE)
{
pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+#ifdef BSD_SELECT
FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT)
+ {
+#ifdef BSD_SELECT
+ FD_SET(osfd, &ex);
+#else
+ socks[npds*2+ex] = osfd;
+ ex++;
+#endif
}
- if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
}
}
else
@@ -178,9 +216,19 @@ PRInt32 _PR_MD_PR_POLL(
}
}
- if (0 != ready) return ready; /* no need to block */
+ if (0 != ready)
+ {
+#ifndef BSD_SELECT
+ free(socks);
+#endif
+ return ready; /* no need to block */
+ }
+
+ remaining = timeout;
+ start = PR_IntervalNow();
retry:
+#ifdef BSD_SELECT
if (timeout != PR_INTERVAL_NO_TIMEOUT)
{
PRInt32 ticksPerSecond = PR_TicksPerSecond();
@@ -191,21 +239,50 @@ retry:
}
ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
- if (ready == -1 && errno == EINTR)
+#else
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT:
+ msecs = 0;
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ msecs = -1;
+ break;
+ default:
+ msecs = PR_IntervalToMilliseconds(remaining);
+ }
+
+ /* compact array */
+ for( i = rd, j = npds; j < npds+wt; i++,j++ )
+ socks[i] = socks[j];
+ for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
+ socks[i] = socks[j];
+
+ ready = _MD_SELECT(socks, rd, wt, ex, msecs);
+#endif
+
+ if (ready == -1 && errno == SOCEINTR)
{
- if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
- else
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ goto retry;
+ else
{
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) ready = 0; /* timed out */
- else
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout)
+ ready = 0; /* timed out */
+ else
{
- remaining = timeout - elapsed;
- goto retry;
+ remaining = timeout - elapsed;
+ goto retry;
}
- }
+ }
}
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
if (ready > 0)
{
ready = 0;
@@ -214,26 +291,44 @@ retry:
PRInt16 out_flags = 0;
if ((NULL != pd->fd) && (0 != pd->in_flags))
{
+ PRInt32 osfd;
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottom);
osfd = bottom->secret->md.osfd;
+#ifdef BSD_SELECT
if (FD_ISSET(osfd, &rd))
+#else
+ if( IsSocketSet(osfd, socks, 0, rd) )
+#endif
{
if (pd->out_flags & _PR_POLL_READ_SYS_READ)
out_flags |= PR_POLL_READ;
if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
out_flags |= PR_POLL_WRITE;
- }
+ }
+
+#ifdef BSD_SELECT
if (FD_ISSET(osfd, &wt))
+#else
+ if( IsSocketSet(osfd, socks, rd, wt) )
+#endif
{
if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
out_flags |= PR_POLL_READ;
if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
out_flags |= PR_POLL_WRITE;
+ }
+
+#ifdef BSD_SELECT
+ if (FD_ISSET(osfd, &ex))
+#else
+ if( IsSocketSet(osfd, socks, rd+wt, ex) )
+#endif
+ {
+ out_flags |= PR_POLL_EXCEPT;
}
- if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
}
pd->out_flags = out_flags;
if (out_flags) ready++;
@@ -242,39 +337,42 @@ retry:
}
else if (ready < 0)
{
- err = _MD_ERRNO();
- if (err == EBADF)
+ err = _MD_ERRNO();
+ if (err == EBADF)
{
- /* Find the bad fds */
- ready = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ /* Find the bad fds */
+ int optval;
+ int optlen = sizeof(optval);
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
{
- int optval;
- int optlen = sizeof(optval);
- pd->out_flags = 0;
- if ((NULL == pd->fd) || (pd->in_flags == 0)) continue;
- bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
- if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
- SO_TYPE, (char *) &optval, &optlen) == -1)
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
{
- PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
- if (_MD_ERRNO() == ENOTSOCK)
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
{
- pd->out_flags = PR_POLL_NVAL;
- ready++;
+ PR_ASSERT(sock_errno() == SOCENOTSOCK);
+ if (sock_errno() == SOCENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
}
}
- }
- PR_ASSERT(ready > 0);
- }
- else
- {
- PR_ASSERT(err != EINTR); /* should have been handled above */
- _PR_MD_MAP_SELECT_ERROR(err);
+ }
+ PR_ASSERT(ready > 0);
}
- }
- return ready;
- }
+ else
+ _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+#ifndef BSD_SELECT
+ free(socks);
+#endif
+ return ready;
+}
#ifdef XP_OS2_EMX
HMTX thread_select_mutex = 0; /* because EMX's select is not thread safe - duh! */
diff --git a/pr/src/md/os2/os2sock.c b/pr/src/md/os2/os2sock.c
index 529e0e5a..36ebd46b 100644
--- a/pr/src/md/os2/os2sock.c
+++ b/pr/src/md/os2/os2sock.c
@@ -46,9 +46,13 @@
#include "primpl.h"
#ifdef XP_OS2_EMX
- #include <sys/time.h> /* For timeval. */
+ #include <sys/time.h> /* For timeval. */
#endif
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+#define READ_FD 1
+#define WRITE_FD 2
+
void
_PR_MD_INIT_IO()
{
@@ -59,34 +63,19 @@ _PR_MD_INIT_IO()
PRInt32
-_PR_MD_SOCKET(int af, int type, int flags)
+_PR_MD_SOCKET(int domain, int type, int flags)
{
- int sock;
- PRUint32 one = 1;
- PRInt32 rv;
- PRInt32 err;
+ PRInt32 osfd, err;
- sock = socket(af, type, flags);
-
- if (sock == -1 )
- {
- int rv = sock_errno();
- soclose(sock);
- _PR_MD_MAP_SOCKET_ERROR(rv);
- return (PRInt32) -1;
- }
+ osfd = socket(domain, type, flags);
- /*
- ** Make the socket Non-Blocking
- */
- rv = ioctl( sock, FIONBIO, (char *) &one, sizeof(one));
- if ( rv != 0 )
+ if (osfd == -1)
{
err = sock_errno();
- return -1;
+ _PR_MD_MAP_SOCKET_ERROR(err);
}
- return (PRInt32)sock;
+ return(osfd);
}
/*
@@ -96,12 +85,13 @@ _PR_MD_SOCKET(int af, int type, int flags)
PRInt32
_MD_CloseSocket(PRInt32 osfd)
{
- PRInt32 rv = -1;
-
- rv = soclose((int) osfd );
- if (rv < 0)
- _PR_MD_MAP_SOCKET_ERROR(sock_errno());
+ PRInt32 rv, err;
+ rv = soclose(osfd);
+ if (rv == -1) {
+ err = sock_errno();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
return rv;
}
@@ -117,256 +107,253 @@ _MD_SocketAvailable(PRFileDesc *fd)
return result;
}
-PRInt32
-_MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
- PRIntervalTime timeout )
+static PRInt32
+socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
+ PRInt32 rv = -1;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRInt32 syserror;
#ifdef BSD_SELECT
- fd_set rd;
- struct timeval tv, *tvp;
-
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
+ struct timeval tv;
+ fd_set rd_wr;
#else
int socks[1];
- socks[0] = osfd;
+ long lTimeout;
#endif
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- while ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
#ifdef BSD_SELECT
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
#else
- if ((rv = _MD_SELECT(socks, 1, 0, 0, -1)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ do {
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ else
+ rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
+#endif
+ if (rv == -1 && (syserror = sock_errno()) != SOCEINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
break;
- }
- }
- else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- break;
- }
- }
- return(rv);
- }
- else if (timeout == PR_INTERVAL_NO_WAIT)
- {
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- else
- {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
- }
- return(rv);
- }
- else
- {
-retry:
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+#ifdef BSD_SELECT
+ FD_ZERO(&rd_wr);
+#endif
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
#ifdef BSD_SELECT
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp);
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
#else
- long lTimeout = PR_IntervalToMilliseconds(timeout);
- rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ lTimeout = PR_IntervalToMilliseconds(remaining);
+ if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000)
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ else
+ rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
#endif
- if (rv > 0) {
- goto retry;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = sock_errno()) != SOCEINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
rv = -1;
- } else {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ break;
}
- } else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == SOCEINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+#ifdef BSD_SELECT
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+#else
+ now += PR_MillisecondsToInterval(lTimeout);
+#endif
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == SOCEINTR));
+ break;
}
- }
return(rv);
-} /* end _MD_Accept() */
+}
+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, (int*)addrlen)) == -1)
+ {
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK) || (err == SOCECONNABORTED))
+ {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+ return(rv);
+}
PRInt32
_PR_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;
- PRInt32 rv;
- int err, len;
-#ifdef BSD_SELECT
-#ifdef XP_OS2//_VACPP
- fd_set wd;
-#else
- fd_set wd, ex;
-#endif #vacpp
- struct timeval tv, *tvp;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
+ /*
+ * 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:
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1)
{
err = sock_errno();
- if ((!fd->secret->nonblocking) && ((err == EINPROGRESS) || (err == EWOULDBLOCK)))
- {
-#ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- tvp = NULL;
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
+
+ if (err == SOCEINTR) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
}
+ goto retry;
+ }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
-#ifdef XP_OS2//_VACPP
- rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp);
-#else
- FD_ZERO(&ex);
- FD_SET(osfd, &ex);
- rv = _MD_SELECT(osfd + 1, NULL, &wd, &ex, tvp);
-#endif #vacpp
-#else #!bsd_select
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- lTimeout = -1;
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
+ if (!fd->secret->nonblocking && (err == SOCEINPROGRESS))
+ {
+ /*
+ * socket_io_wait() may return -1 or 1.
+ */
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
}
-
- socks[0] = osfd;
-#ifdef XP_OS2//_VACPP
- rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
-#else
- rv = _MD_SELECT(socks, 0, 1, 1, lTimeout);
-#endif #vacpp
-#endif
- if (rv > 0)
- {
-#ifdef BSD_SELECT
-#ifdef XP_OS2//_VACPP
- if (FD_ISSET(osfd, &wd))
- {
- //DosSleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- if (err != 0)
- {
- _PR_MD_MAP_CONNECT_ERROR(err);
- return -1;
- }
- else
- return 0; /* it's connected */
- }
- else
- return -1;
-#else
- if (FD_ISSET(osfd, &ex))
- {
- DosSleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- if (err != 0)
- _PR_MD_MAP_CONNECT_ERROR(err);
- else
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- if (FD_ISSET(osfd, &wd))
- {
- /* it's connected */
- return 0;
- }
-#endif #vacpp
-#else #!bsd_select
- if (socks[0] == osfd)
- {
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
-
- if (err != 0)
- {
- _PR_MD_MAP_CONNECT_ERROR(err);
- return -1;
- }
- else
- return 0; /* it's connected */
- }
- else
- return -1;
-#endif
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
}
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return(-1);
- } else if (rv < 0)
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return(-1);
+ err = _MD_os2_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;
-}
+ return rv;
+} /* _MD_connect */
PRInt32
_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
{
- PRInt32 rv;
-
- rv = bind(fd->secret->md.osfd, (struct sockaddr*) &(addr->inet), addrlen);
-
- if (rv == -1) {
- _PR_MD_MAP_BIND_ERROR(sock_errno());
- return -1;
- }
-
- return 0;
+ PRInt32 rv, err;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+ return(rv);
}
@@ -376,70 +363,27 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- int osflags;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- if (0 == flags) {
- osflags = 0;
- } else {
- PR_ASSERT(PR_MSG_PEEK == flags);
- osflags = MSG_PEEK;
- }
- while ((rv = recv( osfd, buf, amount, osflags)) == -1)
+ while ((rv = recv(osfd,buf,amount,flags)) == -1)
{
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
-#else
- socks[0] = osfd;
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1)
-#endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
break;
}
- }
- else
- {
- _PR_MD_MAP_RECV_ERROR(err);
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
- } /* end while() */
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+done:
return(rv);
}
@@ -449,108 +393,42 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- PRInt32 bytesSent = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while(bytesSent < amount )
+ while ((rv = send(osfd,buf,amount,flags)) == -1)
{
- while ((rv = send( osfd, (char *) buf, amount, 0 )) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SEND_ERROR(err);
- return -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
}
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
- if ((rv >= 0) && (bytesSent < amount ))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 0, 1, 0,lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
+ }
+
+ /*
+ * 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 (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
+ rv = -1;
+ goto done;
}
}
- return bytesSent;
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -559,109 +437,29 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- PRInt32 bytesSent = 0;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
-
- while(bytesSent < amount)
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1)
{
- while ((rv = sendto( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- addrlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SENDTO_ERROR(err);
- return -1;
- }
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
- break;
- }
- if ((rv >= 0) && (bytesSent < amount ))
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK))
{
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ if (fd->secret->nonblocking) {
break;
}
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
}
}
- return bytesSent;
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -670,103 +468,86 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- PRUint32 addrlen_temp = *addrlen;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while ((rv = recvfrom( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- (int *) addrlen)) == -1)
+ while( (*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, (int *)addrlen)) == -1))
{
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
-#else
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1)
-#endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- } else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
break;
}
-
- /* recvfrom blows this value away if it fails first time */
- *addrlen = addrlen_temp;
- }
- else
- {
- _PR_MD_MAP_RECVFROM_ERROR(err);
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
}
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+done:
return(rv);
}
PRInt32
-_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout)
{
- int index;
- int sent = 0;
- int rv;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
- for (index=0; index < iov_size; index++)
- {
- rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
- if (rv > 0)
- sent += rv;
- if ( rv != iov[index].iov_len )
- {
- if (rv < 0)
- {
- if (fd->secret->nonblocking
- && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
- && (sent > 0))
- {
- return sent;
- }
- else
- {
- return -1;
- }
+ /*
+ * 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 = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
}
- /* Only a nonblocking socket can have partial sends */
- PR_ASSERT(fd->secret->nonblocking);
- return sent;
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
}
}
- return sent;
+
+ /*
+ * 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 (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -781,63 +562,77 @@ _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
}
PRStatus
-_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getsockname((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKNAME_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getpeername((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETPEERNAME_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ char* optval, PRInt32* optlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getsockopt((int)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ const char* optval, PRInt32 optlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = setsockopt((int)fd->secret->md.osfd, level, optname, (char *) optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_SETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
void
-_MD_MakeNonblock(PRFileDesc *f)
+_MD_MakeNonblock(PRFileDesc *fd)
{
- return; /* do nothing! */
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 err;
+ PRUint32 one = 1;
+
+ if (osfd <= 2) {
+ /* Don't mess around with stdin, stdout or stderr */
+ return;
+ }
+
+ err = ioctl( osfd, FIONBIO, (char *) &one, sizeof(one));
+ if ( err != 0 )
+ {
+ err = sock_errno();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
}