From 7c728b3c7680662fc4e92b5d03697b8339560b08 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 6 Feb 2018 11:40:35 +0100 Subject: Update NSPR to 4.16 --- nsprpub/pr/src/io/prio.c | 4 + nsprpub/pr/src/io/prlayer.c | 59 ++++----- nsprpub/pr/src/io/prmmap.c | 9 +- nsprpub/pr/src/io/prscanf.c | 8 +- nsprpub/pr/src/io/prsocket.c | 115 +++++++++++++++++- nsprpub/pr/src/md/unix/unix.c | 22 ++-- nsprpub/pr/src/md/unix/uxproces.c | 22 ++-- nsprpub/pr/src/md/unix/uxshm.c | 44 +++---- nsprpub/pr/src/md/windows/w32poll.c | 2 +- nsprpub/pr/src/md/windows/w95sock.c | 172 +++++++++++++++++++++++++- nsprpub/pr/src/misc/praton.c | 8 +- nsprpub/pr/src/misc/prnetdb.c | 49 +++----- nsprpub/pr/src/misc/prtime.c | 66 ++++++---- nsprpub/pr/src/misc/prtpool.c | 18 +-- nsprpub/pr/src/prvrsion.c | 7 ++ nsprpub/pr/src/pthreads/ptio.c | 234 ++++++++++++++++++++++++++---------- nsprpub/pr/src/pthreads/ptsynch.c | 5 +- 17 files changed, 629 insertions(+), 215 deletions(-) (limited to 'nsprpub/pr/src') diff --git a/nsprpub/pr/src/io/prio.c b/nsprpub/pr/src/io/prio.c index 78cbdf564..bf9763a2c 100644 --- a/nsprpub/pr/src/io/prio.c +++ b/nsprpub/pr/src/io/prio.c @@ -119,6 +119,10 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc( fd->methods = methods; fd->secret->state = _PR_FILEDESC_OPEN; fd->secret->md.osfd = osfd; +#if defined(_WIN64) + fd->secret->alreadyConnected = PR_FALSE; + fd->secret->overlappedActive = PR_FALSE; +#endif _PR_MD_INIT_FILEDESC(fd); } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); diff --git a/nsprpub/pr/src/io/prlayer.c b/nsprpub/pr/src/io/prlayer.c index cadb7ca3c..00da0287a 100644 --- a/nsprpub/pr/src/io/prlayer.c +++ b/nsprpub/pr/src/io/prlayer.c @@ -47,7 +47,8 @@ static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd) rv = fd->lower->methods->close(fd->lower); _PR_DestroyIOLayer(fd); return rv; - } else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) { + } + if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) { /* * lower layers of new style stack */ @@ -201,16 +202,16 @@ static PRFileDesc* PR_CALLBACK pl_TopAccept ( return NULL; } - if (newstyle_stack) { - newstack->lower = newfd; - newfd->higher = newstack; - return newstack; - } else { - /* this PR_PushIOLayer call cannot fail */ - rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); - PR_ASSERT(PR_SUCCESS == rv); - return newfd; /* that's it */ - } + if (newstyle_stack) + { + newstack->lower = newfd; + newfd->higher = newstack; + return newstack; + } + /* this PR_PushIOLayer call cannot fail */ + rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); + PR_ASSERT(PR_SUCCESS == rv); + return newfd; /* that's it */ } static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr) @@ -326,12 +327,11 @@ static PRInt32 PR_CALLBACK pl_DefAcceptread ( (*nd)->higher = newstack; *nd = newstack; return nbytes; - } else { - /* this PR_PushIOLayer call cannot fail */ - rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); - PR_ASSERT(PR_SUCCESS == rv); - return nbytes; } + /* this PR_PushIOLayer call cannot fail */ + rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); + PR_ASSERT(PR_SUCCESS == rv); + return nbytes; } static PRInt32 PR_CALLBACK pl_DefTransmitfile ( @@ -494,10 +494,9 @@ static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack) { if (NULL == stack) return PR_FAILURE; - else { - PR_DELETE(stack); - return PR_SUCCESS; - } + + PR_DELETE(stack); + return PR_SUCCESS; } /* _PR_DestroyIOLayer */ PR_IMPLEMENT(PRStatus) PR_PushIOLayer( @@ -652,9 +651,11 @@ retry: if ((NULL != names) && (identity < length)) { /* what we did is still okay */ - memcpy( - names, identity_cache.name, - identity_cache.length * sizeof(char*)); + if (identity_cache.length != 0) { + memcpy( + names, identity_cache.name, + identity_cache.length * sizeof(char*)); + } old = identity_cache.name; identity_cache.name = names; identity_cache.length = length; @@ -702,8 +703,8 @@ PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd) if (PR_IO_LAYER_HEAD == fd->identity) { PR_ASSERT(NULL != fd->lower); return fd->lower->identity; - } else - return fd->identity; + } + return fd->identity; } /* PR_GetLayersIdentity */ PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id) @@ -711,10 +712,10 @@ PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity i PRFileDesc *layer = fd; if (PR_TOP_IO_LAYER == id) { - if (PR_IO_LAYER_HEAD == fd->identity) - return fd->lower; - else - return fd; + if (PR_IO_LAYER_HEAD == fd->identity) { + return fd->lower; + } + return fd; } for (layer = fd; layer != NULL; layer = layer->lower) diff --git a/nsprpub/pr/src/io/prmmap.c b/nsprpub/pr/src/io/prmmap.c index 6ffc13305..64f7ed4e8 100644 --- a/nsprpub/pr/src/io/prmmap.c +++ b/nsprpub/pr/src/io/prmmap.c @@ -24,17 +24,16 @@ PR_IMPLEMENT(PRFileMap *) PR_CreateFileMap( || prot == PR_PROT_WRITECOPY); fmap = PR_NEWZAP(PRFileMap); if (NULL == fmap) { - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - return NULL; + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; } fmap->fd = fd; fmap->prot = prot; if (_PR_MD_CREATE_FILE_MAP(fmap, size) == PR_SUCCESS) { - return fmap; - } else { + return fmap; + } PR_DELETE(fmap); return NULL; - } } PR_IMPLEMENT(PRInt32) PR_GetMemMapAlignment(void) diff --git a/nsprpub/pr/src/io/prscanf.c b/nsprpub/pr/src/io/prscanf.c index 9d75d824e..377a6e643 100644 --- a/nsprpub/pr/src/io/prscanf.c +++ b/nsprpub/pr/src/io/prscanf.c @@ -409,7 +409,8 @@ Convert(ScanfState *state, const char *fmt) ch = GET(state); if (ch == EOF) { return NULL; - } else if (state->assign) { + } + if (state->assign) { *cArg++ = ch; } } @@ -602,10 +603,9 @@ StringGetChar(void *stream) if (*cPtr == '\0') { return EOF; - } else { - *((char **) stream) = cPtr + 1; - return (unsigned char) *cPtr; } + *((char **) stream) = cPtr + 1; + return (unsigned char) *cPtr; } static void diff --git a/nsprpub/pr/src/io/prsocket.c b/nsprpub/pr/src/io/prsocket.c index be9702408..a24b8e1bb 100644 --- a/nsprpub/pr/src/io/prsocket.c +++ b/nsprpub/pr/src/io/prsocket.c @@ -7,6 +7,12 @@ #include +#if defined(_WIN64) +#ifndef SO_UPDATE_CONNECT_CONTEXT +#define SO_UPDATE_CONNECT_CONTEXT 0x7010 +#endif +#endif + /************************************************************************/ /* These two functions are only used in assertions. */ @@ -304,6 +310,48 @@ static PRStatus PR_CALLBACK SocketConnectContinue( } PR_ASSERT(out_flags & PR_POLL_WRITE); + +#if defined(_WIN64) + if (fd->secret->alreadyConnected) { + fd->secret->alreadyConnected = PR_FALSE; + } + /* TCP Fast Open on Windows must use ConnectEx, which uses overlapped + * input/output. + * To get result we need to use GetOverlappedResult. */ + if (fd->secret->overlappedActive) { + PR_ASSERT(fd->secret->nonblocking); + PRInt32 rvSent; + if (GetOverlappedResult(osfd, &fd->secret->ol, &rvSent, FALSE) == TRUE) { + fd->secret->overlappedActive = PR_FALSE; + PR_LOG(_pr_io_lm, PR_LOG_MIN, + ("SocketConnectContinue GetOverlappedResult succeeded\n")); + /* 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. */ + if (setsockopt((SOCKET)osfd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) != 0) { + err = WSAGetLastError(); + PR_LOG(_pr_io_lm, PR_LOG_MIN, + ("SocketConnectContinue setting SO_UPDATE_CONNECT_CONTEXT failed %d\n", err)); + _PR_MD_MAP_SETSOCKOPT_ERROR(err); + return PR_FAILURE; + } + return PR_SUCCESS; + } else { + err = WSAGetLastError(); + PR_LOG(_pr_io_lm, PR_LOG_MIN, + ("SocketConnectContinue GetOverlappedResult failed %d\n", err)); + if (err != ERROR_IO_INCOMPLETE) { + _PR_MD_MAP_CONNECT_ERROR(err); + fd->secret->overlappedActive = PR_FALSE; + return PR_FAILURE; + } else { + PR_SetError(PR_IN_PROGRESS_ERROR, 0); + return PR_FAILURE; + } + } + } +#endif + return PR_SUCCESS; #elif defined(XP_OS2) @@ -751,7 +799,7 @@ static PRInt32 PR_CALLBACK SocketSendTo( #endif count = 0; - while (amount > 0) { + do { temp = _PR_MD_SENDTO(fd, buf, amount, flags, addrp, PR_NETADDR_SIZE(addr), timeout); if (temp < 0) { @@ -764,10 +812,60 @@ static PRInt32 PR_CALLBACK SocketSendTo( } buf = (const void*) ((const char*)buf + temp); amount -= temp; - } + } while (amount > 0); return count; } +#if defined(_WIN64) && defined(WIN95) +static PRInt32 PR_CALLBACK SocketTCPSendTo( + PRFileDesc *fd, const void *buf, PRInt32 amount, + PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) +{ + PRInt32 temp, count; + const PRNetAddr *addrp = addr; +#if defined(_PR_INET6) + PRNetAddr addrCopy; +#endif + PRThread *me = _PR_MD_CURRENT_THREAD(); + + if (_PR_PENDING_INTERRUPT(me)) { + me->flags &= ~_PR_INTERRUPT; + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); + return -1; + } + if (_PR_IO_PENDING(me)) { + PR_SetError(PR_IO_PENDING_ERROR, 0); + return -1; + } + + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; + } +#endif + + count = 0; + while (amount > 0) { + temp = _PR_MD_TCPSENDTO(fd, buf, amount, flags, + addrp, PR_NETADDR_SIZE(addr), timeout); + if (temp < 0) { + count = -1; + break; + } + count += temp; + if (fd->secret->nonblocking) { + break; + } + buf = (const void*) ((const char*)buf + temp); + amount -= temp; + } + return count; +} +#endif + static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { @@ -1066,6 +1164,15 @@ static PRInt16 PR_CALLBACK SocketPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { *out_flags = 0; + +#if defined(_WIN64) + if (in_flags & PR_POLL_WRITE) { + if (fd->secret->alreadyConnected) { + out_flags = PR_POLL_WRITE; + return PR_POLL_WRITE; + } + } +#endif return in_flags; } /* SocketPoll */ @@ -1090,7 +1197,11 @@ static PRIOMethods tcpMethods = { SocketRecv, SocketSend, (PRRecvfromFN)_PR_InvalidInt, +#if defined(_WIN64) && defined(WIN95) + SocketTCPSendTo, /* This is for fast open. We imitate Linux interface. */ +#else (PRSendtoFN)_PR_InvalidInt, +#endif SocketPoll, SocketAcceptRead, SocketTransmitFile, 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) diff --git a/nsprpub/pr/src/misc/praton.c b/nsprpub/pr/src/misc/praton.c index bff0cd151..80c0628cc 100644 --- a/nsprpub/pr/src/misc/praton.c +++ b/nsprpub/pr/src/misc/praton.c @@ -177,19 +177,21 @@ pr_inet_aton(const char *cp, PRUint32 *addr) case 2: /*%< a.b -- 8.24 bits */ if (val > 0xffffffU) return (0); - val |= parts[0] << 24; + val |= (unsigned int)parts[0] << 24; break; case 3: /*%< a.b.c -- 8.8.16 bits */ if (val > 0xffffU) return (0); - val |= (parts[0] << 24) | (parts[1] << 16); + val |= ((unsigned int)parts[0] << 24) | ((unsigned int)parts[1] << 16); break; case 4: /*%< a.b.c.d -- 8.8.8.8 bits */ if (val > 0xffU) return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + val |= ((unsigned int)parts[0] << 24) | + ((unsigned int)parts[1] << 16) | + ((unsigned int)parts[2] << 8); break; } *addr = PR_htonl(val); diff --git a/nsprpub/pr/src/misc/prnetdb.c b/nsprpub/pr/src/misc/prnetdb.c index b2f6e435b..affebf6ac 100644 --- a/nsprpub/pr/src/misc/prnetdb.c +++ b/nsprpub/pr/src/misc/prnetdb.c @@ -1405,7 +1405,7 @@ PR_IMPLEMENT(PRStatus) PR_InitializeNetAddr( PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); - if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->inet)); + if (val != PR_IpAddrNull) memset(addr, 0, sizeof(*addr)); addr->inet.family = AF_INET; addr->inet.port = htons(port); switch (val) @@ -1483,19 +1483,21 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) if (val == PR_IpAddrAny) { if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; - } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) - && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) - == htonl(INADDR_ANY)) { - return PR_TRUE; + } + if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) + && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) + == htonl(INADDR_ANY)) { + return PR_TRUE; } } else if (val == PR_IpAddrLoopback) { if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr *)&addr->ipv6.ip)) { - return PR_TRUE; - } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) - && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) - == htonl(INADDR_LOOPBACK)) { return PR_TRUE; } + if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) + && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) + == htonl(INADDR_LOOPBACK)) { + return PR_TRUE; + } } else if (val == PR_IpAddrV4Mapped && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; @@ -1504,8 +1506,9 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) if (addr->raw.family == AF_INET) { if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) { return PR_TRUE; - } else if (val == PR_IpAddrLoopback - && addr->inet.ip == htonl(INADDR_LOOPBACK)) { + } + if (val == PR_IpAddrLoopback + && addr->inet.ip == htonl(INADDR_LOOPBACK)) { return PR_TRUE; } } @@ -1777,18 +1780,12 @@ PR_IMPLEMENT(PRUint64) PR_ntohll(PRUint64 n) #ifdef IS_BIG_ENDIAN return n; #else - PRUint64 tmp; PRUint32 hi, lo; - LL_L2UI(lo, n); - LL_SHR(tmp, n, 32); - LL_L2UI(hi, tmp); + lo = (PRUint32)n; + hi = (PRUint32)(n >> 32); hi = PR_ntohl(hi); lo = PR_ntohl(lo); - LL_UI2L(n, lo); - LL_SHL(n, n, 32); - LL_UI2L(tmp, hi); - LL_ADD(n, n, tmp); - return n; + return ((PRUint64)lo << 32) + (PRUint64)hi; #endif } /* ntohll */ @@ -1797,18 +1794,12 @@ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n) #ifdef IS_BIG_ENDIAN return n; #else - PRUint64 tmp; PRUint32 hi, lo; - LL_L2UI(lo, n); - LL_SHR(tmp, n, 32); - LL_L2UI(hi, tmp); + lo = (PRUint32)n; + hi = (PRUint32)(n >> 32); hi = htonl(hi); lo = htonl(lo); - LL_UI2L(n, lo); - LL_SHL(n, n, 32); - LL_UI2L(tmp, hi); - LL_ADD(n, n, tmp); - return n; + return ((PRUint64)lo << 32) + (PRUint64)hi; #endif } /* htonll */ diff --git a/nsprpub/pr/src/misc/prtime.c b/nsprpub/pr/src/misc/prtime.c index 6735805d8..f03786096 100644 --- a/nsprpub/pr/src/misc/prtime.c +++ b/nsprpub/pr/src/misc/prtime.c @@ -279,8 +279,7 @@ static int IsLeapYear(PRInt16 year) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) return 1; - else - return 0; + return 0; } /* @@ -495,6 +494,20 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) #define MT_safe_localtime localtime_r +#elif defined(_MSC_VER) + +/* Visual C++ has had localtime_s() since Visual C++ 2005. */ + +static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result) +{ + errno_t err = localtime_s(result, clock); + if (err != 0) { + errno = err; + return NULL; + } + return result; +} + #else #define HAVE_LOCALTIME_MONITOR 1 /* We use 'monitor' to serialize our calls @@ -580,6 +593,7 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) PRTimeParameters retVal; struct tm localTime; + struct tm *localTimeResult; time_t secs; PRTime secs64; PRInt64 usecPerSec; @@ -606,7 +620,12 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) */ secs = 86400L; - (void) MT_safe_localtime(&secs, &localTime); + localTimeResult = MT_safe_localtime(&secs, &localTime); + PR_ASSERT(localTimeResult != NULL); + if (localTimeResult == NULL) { + /* Shouldn't happen. Use safe fallback for optimized builds. */ + return PR_GMTParameters(gmt); + } /* GMT is 00:00:00, 2nd of Jan. */ @@ -957,6 +976,7 @@ PR_ParseTimeStringToExplodedTime( int hour = -1; int min = -1; int sec = -1; + struct tm *localTimeResult; const char *rest = string; @@ -1215,7 +1235,7 @@ PR_ParseTimeStringToExplodedTime( if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; - else if ((end - rest) == 2) + if ((end - rest) == 2) tmp_hour = ((rest[0]-'0')*10 + (rest[1]-'0')); else @@ -1230,12 +1250,12 @@ PR_ParseTimeStringToExplodedTime( if (end == rest) /* no digits after first colon? */ break; - else if ((end - rest) > 2) + if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; - else if ((end - rest) == 2) + if ((end - rest) == 2) tmp_min = ((rest[0]-'0')*10 + - (rest[1]-'0')); + (rest[1]-'0')); else tmp_min = (rest[0]-'0'); @@ -1253,7 +1273,7 @@ PR_ParseTimeStringToExplodedTime( else if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; - else if ((end - rest) == 2) + if ((end - rest) == 2) tmp_sec = ((rest[0]-'0')*10 + (rest[1]-'0')); else @@ -1287,7 +1307,7 @@ PR_ParseTimeStringToExplodedTime( rest = end; break; } - else if ((*end == '/' || *end == '-') && + if ((*end == '/' || *end == '-') && end[1] >= '0' && end[1] <= '9') { /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 @@ -1618,7 +1638,11 @@ PR_ParseTimeStringToExplodedTime( zone_offset for the date we are parsing is the same as the zone offset on 00:00:00 2 Jan 1970 GMT. */ secs = 86400; - (void) MT_safe_localtime(&secs, &localTime); + localTimeResult = MT_safe_localtime(&secs, &localTime); + PR_ASSERT(localTimeResult != NULL); + if (localTimeResult == NULL) { + return PR_FAILURE; + } zone_offset = localTime.tm_min + 60 * localTime.tm_hour + 1440 * (localTime.tm_mday - 2); @@ -1989,24 +2013,22 @@ pr_WeekOfYear(const PRExplodedTime* time, unsigned int firstDayOfWeek) dayOfWeek = time->tm_wday - firstDayOfWeek; if (dayOfWeek < 0) dayOfWeek += 7; - - dayOfYear = time->tm_yday - dayOfWeek; + dayOfYear = time->tm_yday - dayOfWeek; if( dayOfYear <= 0 ) { /* If dayOfYear is <= 0, it is in the first partial week of the year. */ return 0; } - else - { - /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there - * are any days left over ( dayOfYear % 7 ). Because we are only counting to - * the first day of the week containing the given time, rather than to the - * actual day representing the given time, any days in week 0 will be "absorbed" - * as extra days in the given week. - */ - return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 ); - } + + /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there + * are any days left over ( dayOfYear % 7 ). Because we are only counting to + * the first day of the week containing the given time, rather than to the + * actual day representing the given time, any days in week 0 will be "absorbed" + * as extra days in the given week. + */ + return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 ); + } diff --git a/nsprpub/pr/src/misc/prtpool.c b/nsprpub/pr/src/misc/prtpool.c index 0671cc19b..c2cc9c803 100644 --- a/nsprpub/pr/src/misc/prtpool.c +++ b/nsprpub/pr/src/misc/prtpool.c @@ -862,16 +862,16 @@ PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, if ((rv == PR_FAILURE) && ((err = PR_GetError()) == PR_IN_PROGRESS_ERROR)){ /* connection pending */ return(queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_CONNECT)); - } else { - /* - * connection succeeded or failed; add to jobq right away - */ - if (rv == PR_FAILURE) - iod->error = err; - else - iod->error = 0; - return(PR_QueueJob(tpool, fn, arg, joinable)); } + /* + * connection succeeded or failed; add to jobq right away + */ + if (rv == PR_FAILURE) + iod->error = err; + else + iod->error = 0; + return(PR_QueueJob(tpool, fn, arg, joinable)); + } /* queue a job, when a timer expires */ diff --git a/nsprpub/pr/src/prvrsion.c b/nsprpub/pr/src/prvrsion.c index 67be53827..be43578ca 100644 --- a/nsprpub/pr/src/prvrsion.c +++ b/nsprpub/pr/src/prvrsion.c @@ -74,6 +74,10 @@ static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING #endif /* XP_UNIX */ +#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) { #ifdef XP_UNIX @@ -88,6 +92,9 @@ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) #endif return &VERSION_DESC_NAME; } /* versionEntryPointType */ +#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif /* prvrsion.c */ diff --git a/nsprpub/pr/src/pthreads/ptio.c b/nsprpub/pr/src/pthreads/ptio.c index e4fe5198b..9dde03191 100644 --- a/nsprpub/pr/src/pthreads/ptio.c +++ b/nsprpub/pr/src/pthreads/ptio.c @@ -164,6 +164,9 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #ifndef TCP_CORK #define TCP_CORK 3 #endif +#ifndef MSG_FASTOPEN +#define MSG_FASTOPEN 0x20000000 +#endif #endif #ifdef _PR_IPV6_V6ONLY_PROBE @@ -821,7 +824,7 @@ retry: op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } - else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) + if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; @@ -850,7 +853,7 @@ static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents) op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } - else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) + if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; @@ -892,7 +895,7 @@ static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents) op->arg3.amount -= iov_index; /* and array length */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } - else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) + if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; @@ -915,7 +918,7 @@ static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents) op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } - else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) + if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; @@ -1542,23 +1545,26 @@ static PRStatus pt_Connect( pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) - PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif +#ifdef _PR_HAVE_SOCKADDR_LEN + PRUint16 md_af = addr->raw.family; +#endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); addr_len = PR_NETADDR_SIZE(addr); -#if defined(_PR_INET6) - if (addr->raw.family == PR_AF_INET6) { - md_af = AF_INET6; -#ifndef _PR_HAVE_SOCKADDR_LEN - addrCopy = *addr; - addrCopy.raw.family = AF_INET6; - addrp = &addrCopy; +#ifdef _PR_INET6 + if (addr->raw.family == PR_AF_INET6) { +#ifdef _PR_HAVE_SOCKADDR_LEN + md_af = AF_INET6; +#else + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; #endif - } + } #endif #ifdef _PR_HAVE_SOCKADDR_LEN @@ -1732,9 +1738,11 @@ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr) pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) - PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif +#ifdef _PR_HAVE_SOCKADDR_LEN + PRUint16 md_af = addr->raw.family; +#endif if (pt_TestAbort()) return PR_FAILURE; @@ -1749,15 +1757,16 @@ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr) } } -#if defined(_PR_INET6) - if (addr->raw.family == PR_AF_INET6) { - md_af = AF_INET6; -#ifndef _PR_HAVE_SOCKADDR_LEN - addrCopy = *addr; - addrCopy.raw.family = AF_INET6; - addrp = &addrCopy; +#ifdef _PR_INET6 + if (addr->raw.family == PR_AF_INET6) { +#ifdef _PR_HAVE_SOCKADDR_LEN + md_af = AF_INET6; +#else + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; #endif - } + } #endif addr_len = PR_NETADDR_SIZE(addr); @@ -1989,22 +1998,25 @@ static PRInt32 pt_SendTo( pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) - PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif +#ifdef _PR_HAVE_SOCKADDR_LEN + PRUint16 md_af = addr->raw.family; +#endif if (pt_TestAbort()) return bytes; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); -#if defined(_PR_INET6) - if (addr->raw.family == PR_AF_INET6) { - md_af = AF_INET6; -#ifndef _PR_HAVE_SOCKADDR_LEN - addrCopy = *addr; - addrCopy.raw.family = AF_INET6; - addrp = &addrCopy; +#ifdef _PR_INET6 + if (addr->raw.family == PR_AF_INET6) { +#ifdef _PR_HAVE_SOCKADDR_LEN + md_af = AF_INET6; +#else + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; #endif - } + } #endif addr_len = PR_NETADDR_SIZE(addr); @@ -2044,6 +2056,101 @@ static PRInt32 pt_SendTo( return bytes; } /* pt_SendTo */ +#if defined(LINUX) || defined(DARWIN) +/* Linux uses SendTo to send data during TCP Fast Open. OSX uses connectx, but + * we will make it imitate the Linux's interface. */ +static PRInt32 pt_TCP_SendTo( + PRFileDesc *fd, const void *buf, + PRInt32 amount, PRIntn flags, const PRNetAddr *addr, + PRIntervalTime timeout) +{ +#if defined(LINUX) || HAS_CONNECTX + PRInt32 syserrno, bytes = -1; + PRBool fNeedContinue = PR_FALSE; + pt_SockLen addr_len; + const PRNetAddr *addrp = addr; +#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) + PRNetAddr addrCopy; +#endif +#ifdef _PR_HAVE_SOCKADDR_LEN + PRUint16 md_af = addr->raw.family; +#endif + + if (pt_TestAbort()) return bytes; + + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); + addr_len = PR_NETADDR_SIZE(addr); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { +#ifdef _PR_HAVE_SOCKADDR_LEN + md_af = AF_INET6; +#else + /* If _PR_INET6 is defined and it is PR_AF_INET6 we set family + * to AF_INET6. */ + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; +#endif + } +#endif + +#ifdef _PR_HAVE_SOCKADDR_LEN + /* if _PR_HAVE_SOCKADDR_LEN is defined and it is PR_AF_INET6 we set family + * to AF_INET6 and we set address length. */ + addrCopy = *addr; + ((struct sockaddr*)&addrCopy)->sa_len = addr_len; + ((struct sockaddr*)&addrCopy)->sa_family = md_af; + addrp = &addrCopy; +#endif + +#ifndef HAS_CONNECTX + bytes = sendto( + fd->secret->md.osfd, buf, amount, MSG_FASTOPEN, + (struct sockaddr*)addrp, addr_len); +#else + sa_endpoints_t endpoints; + endpoints.sae_srcif = 0; + endpoints.sae_srcaddr = NULL; + endpoints.sae_srcaddrlen = 0; + endpoints.sae_dstaddr = (struct sockaddr *)addrp; + endpoints.sae_dstaddrlen = addr_len; + struct iovec iov[1]; + iov[0].iov_base = buf; + iov[0].iov_len = amount; + PRInt32 rv = connectx(fd->secret->md.osfd, &endpoints, SAE_ASSOCID_ANY, + CONNECT_DATA_IDEMPOTENT, iov, 1, &bytes, NULL); +#endif + syserrno = errno; + if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) + && (!fd->secret->nonblocking) ) { + if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; + else fNeedContinue = PR_TRUE; + } + if (fNeedContinue == PR_TRUE) { + pt_Continuation op; + op.arg1.osfd = fd->secret->md.osfd; + op.arg2.buffer = (void*)buf; + op.arg3.amount = amount; + op.arg4.flags = flags; + op.arg5.addr = (PRNetAddr*)addrp; + op.timeout = timeout; + op.result.code = 0; /* initialize the number sent */ + op.function = pt_sendto_cont; + op.event = POLLOUT | POLLPRI; + bytes = pt_Continue(&op); + syserrno = op.syserrno; + } + if (bytes < 0) { + pt_MapError(_PR_MD_MAP_SENDTO_ERROR, syserrno); + } + return bytes; +#else /* !HAS_CONNECTX */ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; +#endif +} /* pt_TCP_SendTo */ +#endif /* LINUX || DARWIN */ + static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { @@ -2767,22 +2874,21 @@ static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr) if (rv == -1) { pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno); return PR_FAILURE; - } else { + } #ifdef _PR_HAVE_SOCKADDR_LEN - /* ignore the sa_len field of struct sockaddr */ - if (addr) - { - addr->raw.family = ((struct sockaddr*)addr)->sa_family; - } + /* ignore the sa_len field of struct sockaddr */ + if (addr) + { + addr->raw.family = ((struct sockaddr*)addr)->sa_family; + } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 - if (AF_INET6 == addr->raw.family) - addr->raw.family = PR_AF_INET6; + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; #endif - PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); - PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); - return PR_SUCCESS; - } + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); + PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); + return PR_SUCCESS; } /* pt_GetSockName */ static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) @@ -2798,22 +2904,21 @@ static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) if (rv == -1) { pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno); return PR_FAILURE; - } else { + } #ifdef _PR_HAVE_SOCKADDR_LEN - /* ignore the sa_len field of struct sockaddr */ - if (addr) - { - addr->raw.family = ((struct sockaddr*)addr)->sa_family; - } + /* ignore the sa_len field of struct sockaddr */ + if (addr) + { + addr->raw.family = ((struct sockaddr*)addr)->sa_family; + } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 - if (AF_INET6 == addr->raw.family) - addr->raw.family = PR_AF_INET6; + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; #endif - PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); - PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); - return PR_SUCCESS; - } + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); + PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); + return PR_SUCCESS; } /* pt_GetPeerName */ static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) @@ -3155,7 +3260,11 @@ static PRIOMethods _pr_tcp_methods = { pt_Recv, pt_Send, (PRRecvfromFN)_PR_InvalidInt, +#if defined(LINUX) || defined(DARWIN) + pt_TCP_SendTo, /* This is for TCP Fast Open. Linux uses SendTo function for this. OSX uses connectx, but we imitate Linux. */ +#else (PRSendtoFN)_PR_InvalidInt, +#endif pt_Poll, pt_AcceptRead, pt_TransmitFile, @@ -3602,8 +3711,8 @@ PR_IMPLEMENT(PRStatus) PR_Delete(const char *name) if (rv == -1) { pt_MapError(_PR_MD_MAP_UNLINK_ERROR, errno); return PR_FAILURE; - } else - return PR_SUCCESS; + } + return PR_SUCCESS; } /* PR_Delete */ PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how) @@ -3727,11 +3836,10 @@ PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name) rv = rmdir(name); if (0 == rv) { - return PR_SUCCESS; - } else { + return PR_SUCCESS; + } pt_MapError(_PR_MD_MAP_RMDIR_ERROR, errno); return PR_FAILURE; - } } /* PR_Rmdir */ @@ -3847,7 +3955,8 @@ static PRInt32 _pr_poll_with_poll( /* now locate the NSPR layer at the bottom of the stack */ PRFileDesc *bottom = PR_GetIdentitiesLayer( pds[index].fd, PR_NSPR_IO_LAYER); - PR_ASSERT(NULL != bottom); /* what to do about that? */ + /* ignore a socket without PR_NSPR_IO_LAYER available */ + pds[index].out_flags = 0; /* pre-condition */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) @@ -4105,7 +4214,8 @@ static PRInt32 _pr_poll_with_select( /* now locate the NSPR layer at the bottom of the stack */ PRFileDesc *bottom = PR_GetIdentitiesLayer( pds[index].fd, PR_NSPR_IO_LAYER); - PR_ASSERT(NULL != bottom); /* what to do about that? */ + /* ignore a socket without PR_NSPR_IO_LAYER available */ + pds[index].out_flags = 0; /* pre-condition */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) diff --git a/nsprpub/pr/src/pthreads/ptsynch.c b/nsprpub/pr/src/pthreads/ptsynch.c index 8663a4c71..251205336 100644 --- a/nsprpub/pr/src/pthreads/ptsynch.c +++ b/nsprpub/pr/src/pthreads/ptsynch.c @@ -55,11 +55,10 @@ void _PR_InitLocks(void) rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); PR_ASSERT(0 == rv); -#ifdef LINUX -#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) +#if (defined(LINUX) && (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) || \ + (defined(FREEBSD) && __FreeBSD_version > 700055) rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP); PR_ASSERT(0 == rv); -#endif #endif rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr); -- cgit v1.2.3