summaryrefslogtreecommitdiffstats
path: root/nsprpub/pr/src/pthreads/ptio.c
diff options
context:
space:
mode:
Diffstat (limited to 'nsprpub/pr/src/pthreads/ptio.c')
-rw-r--r--nsprpub/pr/src/pthreads/ptio.c234
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))