diff options
Diffstat (limited to 'nsprpub/pr/src/md')
-rw-r--r-- | nsprpub/pr/src/md/unix/unix.c | 22 | ||||
-rw-r--r-- | nsprpub/pr/src/md/unix/uxproces.c | 22 | ||||
-rw-r--r-- | nsprpub/pr/src/md/unix/uxshm.c | 44 | ||||
-rw-r--r-- | nsprpub/pr/src/md/windows/w32poll.c | 2 | ||||
-rw-r--r-- | nsprpub/pr/src/md/windows/w95sock.c | 172 |
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) |