Bug 1359938 - Fix socket status events for TCP Fast Open. r=mcmanus

This commit is contained in:
Dragana Damjanovic
2017-05-04 12:15:16 +02:00
parent 6d91eb6ea9
commit 898db49f4a
5 changed files with 125 additions and 7 deletions

View File

@@ -57,17 +57,20 @@ public:
TCPFastOpenSecret()
: mState(WAITING_FOR_CONNECT)
, mFirstPacketBufLen(0)
, mCondition(0)
{}
enum {
CONNECTED,
WAITING_FOR_CONNECTCONTINUE,
COLLECT_DATA_FOR_FIRST_PACKET,
WAITING_FOR_CONNECT
WAITING_FOR_CONNECT,
SOCKET_ERROR_STATE
} mState;
PRNetAddr mAddr;
char mFirstPacketBuf[1460];
uint16_t mFirstPacketBufLen;
PRErrorCode mCondition;
};
static PRStatus
@@ -161,6 +164,9 @@ TCPFastOpenSend(PRFileDesc *fd, const void *buf, PRInt32 amount,
case TCPFastOpenSecret::WAITING_FOR_CONNECT:
PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
return -1;
case TCPFastOpenSecret::SOCKET_ERROR_STATE:
PR_SetError(secret->mCondition, 0);
return -1;
}
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
return PR_FAILURE;
@@ -215,6 +221,9 @@ TCPFastOpenRecv(PRFileDesc *fd, void *buf, PRInt32 amount,
break;
case TCPFastOpenSecret::WAITING_FOR_CONNECT:
PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
break;
case TCPFastOpenSecret::SOCKET_ERROR_STATE:
PR_SetError(secret->mCondition, 0);
}
return rv;
}
@@ -247,6 +256,10 @@ TCPFastOpenConnectContinue(PRFileDesc *fd, PRInt16 out_flags)
SOCKET_LOG(("TCPFastOpenConnectContinue result=%d.\n", rv));
secret->mState = TCPFastOpenSecret::CONNECTED;
break;
case TCPFastOpenSecret::SOCKET_ERROR_STATE:
PR_SetError(secret->mCondition, 0);
rv = PR_FAILURE;
}
return rv;
}
@@ -471,5 +484,59 @@ TCPFastOpenGetBufferSizeLeft(PRFileDesc *fd)
sizeLeft - TFO_TLS_RECORD_HEADER_SIZE : 0;
}
bool
TCPFastOpenGetCurrentBufferSize(PRFileDesc *fd)
{
PRFileDesc *tfoFd = PR_GetIdentitiesLayer(fd, sTCPFastOpenLayerIdentity);
MOZ_RELEASE_ASSERT(tfoFd);
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
TCPFastOpenSecret *secret = reinterpret_cast<TCPFastOpenSecret *>(tfoFd->secret);
return secret->mFirstPacketBufLen;
}
bool
TCPFastOpenFlushBuffer(PRFileDesc *fd)
{
PRFileDesc *tfoFd = PR_GetIdentitiesLayer(fd, sTCPFastOpenLayerIdentity);
MOZ_RELEASE_ASSERT(tfoFd);
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
TCPFastOpenSecret *secret = reinterpret_cast<TCPFastOpenSecret *>(tfoFd->secret);
MOZ_ASSERT(secret->mState == TCPFastOpenSecret::CONNECTED);
if (secret->mFirstPacketBufLen) {
SOCKET_LOG(("TCPFastOpenFlushBuffer - %d bytes to drain from "
"mFirstPacketBufLen.\n",
secret->mFirstPacketBufLen ));
PRInt32 rv = (tfoFd->lower->methods->send)(tfoFd->lower,
secret->mFirstPacketBuf,
secret->mFirstPacketBufLen,
0, // flags
PR_INTERVAL_NO_WAIT);
if (rv <= 0) {
PRErrorCode err = PR_GetError();
if (err == PR_WOULD_BLOCK_ERROR) {
// We still need to send this data.
return true;
} else {
// There is an error, let nsSocketTransport pick it up properly.
secret->mCondition = err;
secret->mState = TCPFastOpenSecret::SOCKET_ERROR_STATE;
return false;
}
}
secret->mFirstPacketBufLen -= rv;
if (secret->mFirstPacketBufLen) {
memmove(secret->mFirstPacketBuf,
secret->mFirstPacketBuf + rv,
secret->mFirstPacketBufLen);
}
}
return secret->mFirstPacketBufLen;
}
}
}