summaryrefslogtreecommitdiffstats
path: root/nsprpub/pr/src/md
diff options
context:
space:
mode:
Diffstat (limited to 'nsprpub/pr/src/md')
-rw-r--r--nsprpub/pr/src/md/unix/unix.c22
-rw-r--r--nsprpub/pr/src/md/unix/uxproces.c22
-rw-r--r--nsprpub/pr/src/md/unix/uxshm.c44
-rw-r--r--nsprpub/pr/src/md/windows/w32poll.c2
-rw-r--r--nsprpub/pr/src/md/windows/w95sock.c172
5 files changed, 215 insertions, 47 deletions
diff --git a/nsprpub/pr/src/md/unix/unix.c b/nsprpub/pr/src/md/unix/unix.c
index fdae1199c..662f561b6 100644
--- a/nsprpub/pr/src/md/unix/unix.c
+++ b/nsprpub/pr/src/md/unix/unix.c
@@ -3316,11 +3316,11 @@ int _MD_unix_get_nonblocking_connect_error(int osfd)
return errno;
} else {
return err;
- }
+ }
}
} else {
return ECONNREFUSED;
- }
+ }
#elif defined(UNIXWARE)
/*
* getsockopt() fails with EPIPE, so use getmsg() instead.
@@ -3331,17 +3331,17 @@ int _MD_unix_get_nonblocking_connect_error(int osfd)
rv = getmsg(osfd, NULL, NULL, &flags);
PR_ASSERT(-1 == rv || 0 == rv);
if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
- return errno;
+ return errno;
}
- return 0; /* no error */
+ return 0; /* no error */
#else
- int err;
- _PRSockLen_t optlen = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
- return errno;
- } else {
- return err;
- }
+ int err;
+ _PRSockLen_t optlen = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen) == -1) {
+ return errno;
+ }
+ return err;
+
#endif
}
diff --git a/nsprpub/pr/src/md/unix/uxproces.c b/nsprpub/pr/src/md/unix/uxproces.c
index a3b35e540..5286b9e18 100644
--- a/nsprpub/pr/src/md/unix/uxproces.c
+++ b/nsprpub/pr/src/md/unix/uxproces.c
@@ -247,13 +247,14 @@ ForkAndExec(
PR_DELETE(newEnvp);
}
return NULL;
- } else if (0 == process->md.pid) { /* the child process */
- /*
- * If the child process needs to exit, it must call _exit().
- * Do not call exit(), because exit() will flush and close
- * the standard I/O file descriptors, and hence corrupt
- * the parent process's standard I/O data structures.
- */
+ }
+ if (0 == process->md.pid) { /* the child process */
+ /*
+ * If the child process needs to exit, it must call _exit().
+ * Do not call exit(), because exit() will flush and close
+ * the standard I/O file descriptors, and hence corrupt
+ * the parent process's standard I/O data structures.
+ */
#if !defined(NTO) && !defined(SYMBIAN)
if (attr) {
@@ -498,10 +499,9 @@ ExtractExitStatus(int rawExitStatus)
#endif
if (WIFEXITED(rawExitStatus)) {
return WEXITSTATUS(rawExitStatus);
- } else {
+ }
PR_ASSERT(WIFSIGNALED(rawExitStatus));
return _PR_SIGNALED_EXITSTATUS;
- }
}
static void
@@ -624,8 +624,8 @@ static void WaitPidDaemonThread(void *unused)
} while (sizeof(buf) == rv || (-1 == rv && EINTR == errno));
#ifdef _PR_SHARE_CLONES
- PR_Unlock(pr_wp.ml);
while ((op = pr_wp.opHead) != NULL) {
+ PR_Unlock(pr_wp.ml);
op->process = ForkAndExec(op->path, op->argv,
op->envp, op->attr);
if (NULL == op->process) {
@@ -639,8 +639,8 @@ static void WaitPidDaemonThread(void *unused)
}
op->done = PR_TRUE;
PR_NotifyCondVar(op->doneCV);
- PR_Unlock(pr_wp.ml);
}
+ PR_Unlock(pr_wp.ml);
#endif
while (1) {
diff --git a/nsprpub/pr/src/md/unix/uxshm.c b/nsprpub/pr/src/md/unix/uxshm.c
index dec4e3a7a..54e68191c 100644
--- a/nsprpub/pr/src/md/unix/uxshm.c
+++ b/nsprpub/pr/src/md/unix/uxshm.c
@@ -76,8 +76,8 @@ extern PRSharedMemory * _MD_OpenSharedMemory(
/* copy args to struct */
strcpy( shm->ipcname, ipcname );
- shm->size = size;
- shm->mode = mode;
+ shm->size = size;
+ shm->mode = mode;
shm->flags = flags;
shm->ident = _PR_SHM_IDENT;
@@ -500,30 +500,32 @@ extern PRFileMap* _md_OpenAnonFileMap(
("_md_OpenAnonFileMap(): PR_snprintf(): failed, generating filename"));
goto Finished;
}
-
+
/* create the file */
- osfd = open( genName, (O_CREAT | O_EXCL | O_RDWR), mode );
- if ( -1 == osfd ) {
- if ( EEXIST == errno ) {
- PR_smprintf_free( genName );
- continue; /* name exists, try again */
- } else {
- _PR_MD_MAP_OPEN_ERROR( errno );
- PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
- ("_md_OpenAnonFileMap(): open(): failed, filename: %s, errno: %d",
- genName, PR_GetOSError()));
- PR_smprintf_free( genName );
- goto Finished;
- }
+ osfd = open(genName, (O_CREAT | O_EXCL | O_RDWR), mode);
+ if (-1 == osfd) {
+ if (EEXIST == errno) {
+ PR_smprintf_free(genName);
+ continue; /* name exists, try again */
+ }
+ _PR_MD_MAP_OPEN_ERROR(errno);
+ PR_LOG(
+ _pr_shma_lm,
+ PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): open(): failed, filename: %s, errno: %d",
+ genName,
+ PR_GetOSError()));
+ PR_smprintf_free(genName);
+ goto Finished;
}
break; /* name generation and open successful, break; */
} /* end for() */
- if ( incr == maxTries ) {
- PR_ASSERT( -1 == osfd );
- PR_ASSERT( EEXIST == errno );
- _PR_MD_MAP_OPEN_ERROR( errno );
- goto Finished;
+ if (incr == maxTries) {
+ PR_ASSERT(-1 == osfd);
+ PR_ASSERT(EEXIST == errno);
+ _PR_MD_MAP_OPEN_ERROR(errno);
+ goto Finished;
}
urc = unlink( genName );
diff --git a/nsprpub/pr/src/md/windows/w32poll.c b/nsprpub/pr/src/md/windows/w32poll.c
index 84100763b..daf14dfe0 100644
--- a/nsprpub/pr/src/md/windows/w32poll.c
+++ b/nsprpub/pr/src/md/windows/w32poll.c
@@ -155,7 +155,7 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
pd->out_flags = 0; /* pre-condition */
/* make sure this is an NSPR supported stack */
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
- // ignore a socket without PR_NSPR_IO_LAYER available.
+ /* ignore a socket without PR_NSPR_IO_LAYER available */
if ((NULL != bottom)
&& (_PR_FILEDESC_OPEN == bottom->secret->state))
diff --git a/nsprpub/pr/src/md/windows/w95sock.c b/nsprpub/pr/src/md/windows/w95sock.c
index 1c3ddd911..0429c655a 100644
--- a/nsprpub/pr/src/md/windows/w95sock.c
+++ b/nsprpub/pr/src/md/windows/w95sock.c
@@ -294,8 +294,7 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
PRInt32 rv, err;
PRInt32 bytesSent = 0;
- while(bytesSent < amount)
- {
+ do {
while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr,
addrlen)) == -1)
{
@@ -327,10 +326,177 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
return -1;
}
}
- }
+ } while(bytesSent < amount);
return bytesSent;
}
+#if defined(_WIN64)
+
+static PRCallOnceType _pr_has_connectex_once;
+typedef BOOL (PASCAL FAR * _pr_win_connectex_ptr)(_In_ SOCKET s, _In_reads_bytes_(namelen) const struct sockaddr FAR *name, _In_ int namelen, _In_reads_bytes_opt_(dwSendDataLength) PVOID lpSendBuffer, _In_ DWORD dwSendDataLength, _Out_ LPDWORD lpdwBytesSent, _Inout_ LPOVERLAPPED lpOverlapped);
+
+#ifndef WSAID_CONNECTEX
+#define WSAID_CONNECTEX \
+ {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
+#endif
+#ifndef SIO_GET_EXTENSION_FUNCTION_POINTER
+#define SIO_GET_EXTENSION_FUNCTION_POINTER 0xC8000006
+#endif
+#ifndef TCP_FASTOPEN
+#define TCP_FASTOPEN 15
+#endif
+
+#ifndef SO_UPDATE_CONNECT_CONTEXT
+#define SO_UPDATE_CONNECT_CONTEXT 0x7010
+#endif
+
+static _pr_win_connectex_ptr _pr_win_connectex = NULL;
+
+static PRStatus PR_CALLBACK _pr_set_connectex(void)
+{
+ _pr_win_connectex = NULL;
+ SOCKET sock;
+ PRInt32 dwBytes;
+ int rc;
+
+ /* Dummy socket needed for WSAIoctl */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == INVALID_SOCKET)
+ return PR_SUCCESS;
+
+ GUID guid = WSAID_CONNECTEX;
+ rc = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &guid, sizeof(guid),
+ &_pr_win_connectex, sizeof(_pr_win_connectex),
+ &dwBytes, NULL, NULL);
+ if (rc != 0) {
+ _pr_win_connectex = NULL;
+ return PR_SUCCESS;
+ }
+
+ rc = closesocket(sock);
+ return PR_SUCCESS;
+}
+
+PRInt32
+_PR_MD_TCPSENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ if (PR_CallOnce(&_pr_has_connectex_once, _pr_set_connectex) != PR_SUCCESS) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (_pr_win_connectex == NULL) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ PROsfd osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRInt32 bytesSent = 0;
+ DWORD rvSent;
+
+ BOOL option = 1;
+ rv = setsockopt((SOCKET)osfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&option, sizeof(option));
+ if (rv != 0) {
+ err = WSAGetLastError();
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("_PR_MD_TCPSENDTO error set opt TCP_FASTOPEN failed %d\n", err));
+ if (err == WSAENOPROTOOPT) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ } else {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ }
+ return -1;
+ }
+
+ /* ConnectEx requires the socket to be initially bound. We will use INADDR_ANY. */
+ PRNetAddr bindAddr;
+ memset(&bindAddr, 0, sizeof(bindAddr));
+ bindAddr.raw.family = addr->raw.family;
+
+ rv = bind((SOCKET)osfd, (const struct sockaddr *)&(bindAddr.inet), PR_NETADDR_SIZE(&bindAddr));
+ if (rv != 0) {
+ err = WSAGetLastError();
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("_PR_MD_TCPSENDTO error bind failed %d\n", err));
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ return -1;
+ }
+
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("_PR_MD_TCPSENDTO calling _pr_win_connectex %d %p\n", amount, (char*)buf));
+
+ rvSent = 0;
+ memset(&fd->secret->ol, 0, sizeof(fd->secret->ol));
+ /* ConnectEx return TRUE on a success and FALSE on an error. */
+ if (_pr_win_connectex( (SOCKET)osfd, (struct sockaddr *) addr,
+ addrlen, buf, amount,
+ &rvSent, &fd->secret->ol) == TRUE) {
+ /* When ConnectEx is used, all previously set socket options and
+ * property are not enabled and to enable them
+ * SO_UPDATE_CONNECT_CONTEXT option need to be set. */
+ rv = setsockopt((SOCKET)osfd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
+ if (rv != 0) {
+ err = WSAGetLastError();
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("_PR_MD_TCPSENDTO setting SO_UPDATE_CONNECT_CONTEXT failed %d\n", err));
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ return -1;
+ }
+ /* We imitate Linux here. SendTo will return number of bytes send but
+ * it can not return connection success at the same time, so we return
+ * number of bytes send and "connection success" will be return on the
+ * connectcontinue. */
+ fd->secret->alreadyConnected = PR_TRUE;
+ return rvSent;
+ } else {
+ err = WSAGetLastError();
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("_PR_MD_TCPSENDTO error _pr_win_connectex failed %d\n", err));
+ if (err != ERROR_IO_PENDING) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ } else if (fd->secret->nonblocking) {
+ /* Remember that overlapped structure is set. We will need to get
+ * the final result of ConnectEx call. */
+ fd->secret->overlappedActive = PR_TRUE;
+
+ /* ConnectEx will copy supplied data to a internal buffer and send
+ * them during Fast Open or after connect. Therefore we can assumed
+ * this data already send. */
+ if (amount > 0) {
+ return amount;
+ }
+
+ _PR_MD_MAP_CONNECT_ERROR(WSAEWOULDBLOCK);
+ return -1;
+ }
+ // err is ERROR_IO_PENDING and socket is blocking, so query
+ // GetOverlappedResult.
+ err = ERROR_IO_INCOMPLETE;
+ while (err == ERROR_IO_INCOMPLETE) {
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 ) {
+ return -1;
+ }
+ rv = GetOverlappedResult(osfd, &fd->secret->ol, &rvSent, FALSE);
+ if ( rv == TRUE ) {
+ return rvSent;
+ } else {
+ err = WSAGetLastError();
+ if (err != ERROR_IO_INCOMPLETE) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ }
+ }
+ }
+ return -1;
+}
+#endif
+
PRInt32
_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)