diff options
Diffstat (limited to 'nsprpub/pr/src/pthreads/ptio.c')
-rw-r--r-- | nsprpub/pr/src/pthreads/ptio.c | 234 |
1 files changed, 172 insertions, 62 deletions
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)) |