Bug 1426887 - Avoid adding/removing streams to nsMultiplexInputStream when reading in Presentation API, r=jdm

This commit is contained in:
Andrea Marchesini 2017-12-30 12:47:12 +01:00
parent b672b51cf7
commit e832cff45e
2 changed files with 50 additions and 58 deletions

View File

@ -61,7 +61,7 @@ CopierCallbacks::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsre
NS_IMPL_CYCLE_COLLECTION(PresentationTCPSessionTransport, mTransport, NS_IMPL_CYCLE_COLLECTION(PresentationTCPSessionTransport, mTransport,
mSocketInputStream, mSocketOutputStream, mSocketInputStream, mSocketOutputStream,
mInputStreamPump, mInputStreamScriptable, mInputStreamPump, mInputStreamScriptable,
mMultiplexStream, mMultiplexStreamCopier, mCallback) mCallback)
NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationTCPSessionTransport) NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationTCPSessionTransport)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport) NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport)
@ -236,36 +236,6 @@ PresentationTCPSessionTransport::CreateStream()
return rv; return rv;
} }
mMultiplexStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(mMultiplexStream);
mMultiplexStreamCopier = do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
if (NS_WARN_IF(!sts)) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
rv = mMultiplexStreamCopier->Init(stream,
mSocketOutputStream,
target,
true, /* source buffered */
false, /* sink buffered */
BUFFER_SIZE,
false, /* close source */
false); /* close sink */
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK; return NS_OK;
} }
@ -347,23 +317,59 @@ PresentationTCPSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
return mTransport->GetScriptableSelfAddr(aSelfAddress); return mTransport->GetScriptableSelfAddr(aSelfAddress);
} }
void nsresult
PresentationTCPSessionTransport::EnsureCopying() PresentationTCPSessionTransport::EnsureCopying()
{ {
if (mAsyncCopierActive) { if (mAsyncCopierActive) {
return; return NS_OK;
} }
mAsyncCopierActive = true; mAsyncCopierActive = true;
nsresult rv;
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(multiplexStream);
while (!mPendingData.IsEmpty()) {
nsCOMPtr<nsIInputStream> stream = mPendingData[0];
multiplexStream->AppendStream(stream);
mPendingData.RemoveElementAt(0);
}
nsCOMPtr<nsIAsyncStreamCopier> copier =
do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISocketTransportService> sts =
do_GetService("@mozilla.org/network/socket-transport-service;1");
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
rv = copier->Init(stream,
mSocketOutputStream,
target,
true, /* source buffered */
false, /* sink buffered */
BUFFER_SIZE,
false, /* close source */
false); /* close sink */
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<CopierCallbacks> callbacks = new CopierCallbacks(this); RefPtr<CopierCallbacks> callbacks = new CopierCallbacks(this);
Unused << NS_WARN_IF(NS_FAILED(mMultiplexStreamCopier->AsyncCopy(callbacks, nullptr))); rv = copier->AsyncCopy(callbacks, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
} }
void void
PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus) PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus)
{ {
mAsyncCopierActive = false; mAsyncCopierActive = false;
mMultiplexStream->RemoveStream(0);
if (NS_WARN_IF(NS_FAILED(aStatus))) { if (NS_WARN_IF(NS_FAILED(aStatus))) {
if (mReadyState != ReadyState::CLOSED) { if (mReadyState != ReadyState::CLOSED) {
mCloseStatus = aStatus; mCloseStatus = aStatus;
@ -372,13 +378,7 @@ PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus)
return; return;
} }
uint32_t count; if (!mPendingData.IsEmpty()) {
nsresult rv = mMultiplexStream->GetCount(&count);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (count) {
EnsureCopying(); EnsureCopying();
return; return;
} }
@ -410,7 +410,7 @@ PresentationTCPSessionTransport::Send(const nsAString& aData)
return NS_ERROR_DOM_INVALID_STATE_ERR; return NS_ERROR_DOM_INVALID_STATE_ERR;
} }
mMultiplexStream->AppendStream(stream); mPendingData.AppendElement(stream);
EnsureCopying(); EnsureCopying();
@ -441,9 +441,8 @@ PresentationTCPSessionTransport::Close(nsresult aReason)
mCloseStatus = aReason; mCloseStatus = aReason;
SetReadyState(ReadyState::CLOSING); SetReadyState(ReadyState::CLOSING);
uint32_t count = 0; if (!mAsyncCopierActive) {
mMultiplexStream->GetCount(&count); mPendingData.Clear();
if (!count) {
mSocketOutputStream->Close(); mSocketOutputStream->Close();
} }
@ -540,15 +539,9 @@ PresentationTCPSessionTransport::OnStopRequest(nsIRequest* aRequest,
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
uint32_t count;
nsresult rv = mMultiplexStream->GetCount(&count);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mInputStreamPump = nullptr; mInputStreamPump = nullptr;
if (count != 0 && NS_SUCCEEDED(aStatusCode)) { if (mAsyncCopierActive && NS_SUCCEEDED(aStatusCode)) {
// If we have some buffered output still, and status is not an error, the // If we have some buffered output still, and status is not an error, the
// other side has done a half-close, but we don't want to be in the close // other side has done a half-close, but we don't want to be in the close
// state until we are done sending everything that was buffered. We also // state until we are done sending everything that was buffered. We also

View File

@ -64,7 +64,7 @@ private:
nsresult CreateInputStreamPump(); nsresult CreateInputStreamPump();
void EnsureCopying(); nsresult EnsureCopying();
enum class ReadyState { enum class ReadyState {
CONNECTING, CONNECTING,
@ -96,12 +96,11 @@ private:
nsCOMPtr<nsIInputStreamPump> mInputStreamPump; nsCOMPtr<nsIInputStreamPump> mInputStreamPump;
nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable; nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable;
// Output stream machinery
nsCOMPtr<nsIMultiplexInputStream> mMultiplexStream;
nsCOMPtr<nsIAsyncStreamCopier> mMultiplexStreamCopier;
nsCOMPtr<nsIPresentationSessionTransportCallback> mCallback; nsCOMPtr<nsIPresentationSessionTransportCallback> mCallback;
nsCOMPtr<nsIPresentationSessionTransportBuilderListener> mListener; nsCOMPtr<nsIPresentationSessionTransportBuilderListener> mListener;
// The data to be sent.
nsTArray<nsCOMPtr<nsIInputStream>> mPendingData;
}; };
} // namespace dom } // namespace dom