зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1818756 - Propagate stream error code from client to server, r=jesup,necko-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D171267
This commit is contained in:
Родитель
be7e0b20ea
Коммит
7f20106a49
|
@ -7,6 +7,8 @@
|
|||
#include "mozilla/dom/UnderlyingSinkCallbackHelpers.h"
|
||||
#include "StreamUtils.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "mozilla/dom/WebTransportError.h"
|
||||
#include "nsHttp.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -253,9 +255,22 @@ already_AddRefed<Promise> WritableStreamToOutput::AbortCallbackImpl(
|
|||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// Step 3. Let abortAlgorithmWrapper be an algorithm that runs these steps:
|
||||
|
||||
if (aReason.WasPassed() && aReason.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> obj(aCx, &aReason.Value().toObject());
|
||||
RefPtr<WebTransportError> error;
|
||||
UnwrapObject<prototypes::id::WebTransportError, WebTransportError>(
|
||||
obj, error, nullptr);
|
||||
if (error) {
|
||||
mOutput->CloseWithStatus(net::GetNSResultFromWebTransportError(
|
||||
error->GetStreamErrorCode().Value()));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX The close or rather a dedicated abort should be async. For now we have
|
||||
// to always fall back to the Step 3.3 below.
|
||||
mOutput->CloseWithStatus(NS_ERROR_ABORT);
|
||||
// XXX how do we know this stream is used by webtransport?
|
||||
mOutput->CloseWithStatus(NS_ERROR_WEBTRANSPORT_CODE_BASE);
|
||||
|
||||
// Step 3.3. Return a promise resolved with undefined.
|
||||
// Wrapper handles this
|
||||
|
|
|
@ -1758,17 +1758,16 @@ void Http3Session::CloseWebTransportStream(Http3WebTransportStream* aStream,
|
|||
HTTP3_APP_ERROR_REQUEST_CANCELLED);
|
||||
}
|
||||
|
||||
aStream->Close(aResult);
|
||||
CloseStreamInternal(aStream, aResult);
|
||||
}
|
||||
|
||||
void Http3Session::ResetWebTransportStream(Http3WebTransportStream* aStream,
|
||||
uint8_t aErrorCode) {
|
||||
uint64_t aErrorCode) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG3(("Http3Session::ResetWebTransportStream %p %p 0x%" PRIx32, this, aStream,
|
||||
static_cast<uint32_t>(aErrorCode)));
|
||||
LOG3(("Http3Session::ResetWebTransportStream %p %p 0x%" PRIx64, this, aStream,
|
||||
aErrorCode));
|
||||
mHttp3Connection->ResetStream(aStream->StreamId(), aErrorCode);
|
||||
|
||||
CloseStreamInternal(aStream, NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
void Http3Session::StreamStopSending(Http3WebTransportStream* aStream,
|
||||
|
|
|
@ -207,7 +207,7 @@ class Http3Session final : public nsAHttpTransaction, public nsAHttpConnection {
|
|||
nsresult aResult);
|
||||
void StreamHasDataToWrite(Http3StreamBase* aStream);
|
||||
void ResetWebTransportStream(Http3WebTransportStream* aStream,
|
||||
uint8_t aErrorCode);
|
||||
uint64_t aErrorCode);
|
||||
void StreamStopSending(Http3WebTransportStream* aStream, uint8_t aErrorCode);
|
||||
|
||||
void SendDatagram(Http3WebTransportSession* aSession,
|
||||
|
|
|
@ -400,6 +400,15 @@ nsresult Http3WebTransportStream::ReadSegments() {
|
|||
rv = mSendStreamPipeIn->AsyncWait(this, 0, 0, gSocketTransportService);
|
||||
}
|
||||
again = false;
|
||||
|
||||
// Got a WebTransport specific error
|
||||
if (rv >= NS_ERROR_WEBTRANSPORT_CODE_BASE &&
|
||||
rv <= NS_ERROR_WEBTRANSPORT_CODE_END) {
|
||||
uint8_t errorCode = GetWebTransportErrorFromNSResult(rv);
|
||||
mSendState = SEND_DONE;
|
||||
Reset(WebTransportErrorToHttp3Error(errorCode));
|
||||
rv = NS_OK;
|
||||
}
|
||||
} else if (NS_FAILED(mSocketOutCondition)) {
|
||||
if (mSocketOutCondition != NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
rv = mSocketOutCondition;
|
||||
|
@ -491,6 +500,10 @@ nsresult Http3WebTransportStream::WritePipeSegment(nsIOutputStream* stream,
|
|||
|
||||
nsresult Http3WebTransportStream::WriteSegments() {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
if (!mReceiveStreamPipeOut) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LOG(("Http3WebTransportStream::WriteSegments [this=%p]", this));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -529,8 +542,7 @@ nsresult Http3WebTransportStream::WriteSegments() {
|
|||
}
|
||||
|
||||
bool Http3WebTransportStream::Done() const {
|
||||
// To be implemented in bug 1790403.
|
||||
return false;
|
||||
return mSendState == SEND_DONE && mRecvState == RECV_DONE;
|
||||
}
|
||||
|
||||
void Http3WebTransportStream::Close(nsresult aResult) {
|
||||
|
@ -555,7 +567,7 @@ void Http3WebTransportStream::SendFin() {
|
|||
LOG(("Http3WebTransportStream::SendFin [this=%p mSendState=%d]", this,
|
||||
mSendState));
|
||||
|
||||
if (mSendFin || !mSession) {
|
||||
if (mSendFin || !mSession || mResetError) {
|
||||
// Already closed.
|
||||
return;
|
||||
}
|
||||
|
@ -582,12 +594,12 @@ void Http3WebTransportStream::SendFin() {
|
|||
}
|
||||
}
|
||||
|
||||
void Http3WebTransportStream::Reset(uint8_t aErrorCode) {
|
||||
void Http3WebTransportStream::Reset(uint64_t aErrorCode) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG(("Http3WebTransportStream::Reset [this=%p, mSendState=%d]", this,
|
||||
mSendState));
|
||||
|
||||
if (mResetError || !mSession) {
|
||||
if (mResetError || !mSession || mSendFin) {
|
||||
// The stream is already reset.
|
||||
return;
|
||||
}
|
||||
|
@ -606,6 +618,7 @@ void Http3WebTransportStream::Reset(uint8_t aErrorCode) {
|
|||
NS_NewRunnableFunction("Http3WebTransportStream::Reset", [self]() {
|
||||
self->mSession->ResetWebTransportStream(self, *self->mResetError);
|
||||
self->mSession->StreamHasDataToWrite(self);
|
||||
self->mSession->ConnectSlowConsumer(self);
|
||||
}));
|
||||
});
|
||||
} break;
|
||||
|
@ -616,6 +629,7 @@ void Http3WebTransportStream::Reset(uint8_t aErrorCode) {
|
|||
mSession->ResetWebTransportStream(this, *mResetError);
|
||||
// StreamHasDataToWrite needs to be called to trigger ProcessOutput.
|
||||
mSession->StreamHasDataToWrite(this);
|
||||
mSession->ConnectSlowConsumer(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("invalid mSendState!");
|
||||
|
|
|
@ -61,7 +61,7 @@ class Http3WebTransportStream final : public Http3StreamBase,
|
|||
WebTransportStreamType StreamType() const { return mStreamType; }
|
||||
|
||||
void SendFin();
|
||||
void Reset(uint8_t aErrorCode);
|
||||
void Reset(uint64_t aErrorCode);
|
||||
void SendStopSending(uint8_t aErrorCode);
|
||||
|
||||
already_AddRefed<nsIWebTransportSendStreamStats> GetSendStreamStats();
|
||||
|
@ -121,7 +121,7 @@ class Http3WebTransportStream final : public Http3StreamBase,
|
|||
uint64_t mTotalAcknowledged = 0;
|
||||
bool mSendFin{false};
|
||||
// The error code used to reset the stream. Should be only set once.
|
||||
Maybe<uint8_t> mResetError;
|
||||
Maybe<uint64_t> mResetError;
|
||||
// The error code used for STOP_SENDING. Should be only set once.
|
||||
Maybe<uint8_t> mStopSendingError;
|
||||
|
||||
|
|
|
@ -38,6 +38,10 @@ const uint32_t kHttp3VersionCount = 5;
|
|||
const nsCString kHttp3Versions[] = {"h3-29"_ns, "h3-30"_ns, "h3-31"_ns,
|
||||
"h3-32"_ns, "h3"_ns};
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3/#section-4.3
|
||||
constexpr uint64_t kWebTransportErrorCodeStart = 0x52e4a40fa8db;
|
||||
constexpr uint64_t kWebTransportErrorCodeEnd = 0x52e4a40fa9e2;
|
||||
|
||||
// define storage for all atoms
|
||||
namespace nsHttp {
|
||||
#define HTTP_ATOM(_name, _value) nsHttpAtom _name(nsLiteralCString{_value});
|
||||
|
@ -1081,5 +1085,41 @@ void CreatePushHashKey(const nsCString& scheme, const nsCString& hostHeader,
|
|||
outKey.Append(pathInfo);
|
||||
}
|
||||
|
||||
nsresult GetNSResultFromWebTransportError(uint8_t aErrorCode) {
|
||||
return static_cast<nsresult>((uint32_t)NS_ERROR_WEBTRANSPORT_CODE_BASE +
|
||||
(uint32_t)aErrorCode);
|
||||
}
|
||||
|
||||
uint8_t GetWebTransportErrorFromNSResult(nsresult aResult) {
|
||||
if (aResult < NS_ERROR_WEBTRANSPORT_CODE_BASE ||
|
||||
aResult > NS_ERROR_WEBTRANSPORT_CODE_END) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<uint8_t>((uint32_t)aResult -
|
||||
(uint32_t)NS_ERROR_WEBTRANSPORT_CODE_BASE);
|
||||
}
|
||||
|
||||
uint64_t WebTransportErrorToHttp3Error(uint8_t aErrorCode) {
|
||||
return kWebTransportErrorCodeStart + aErrorCode + aErrorCode / 0x1e;
|
||||
}
|
||||
|
||||
uint8_t Http3ErrorToWebTransportError(uint64_t aErrorCode) {
|
||||
// Ensure the code is within the valid range.
|
||||
if (aErrorCode < kWebTransportErrorCodeStart ||
|
||||
aErrorCode > kWebTransportErrorCodeEnd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t shifted = aErrorCode - kWebTransportErrorCodeStart;
|
||||
uint64_t result = shifted - shifted / 0x1f;
|
||||
|
||||
if (result <= std::numeric_limits<uint8_t>::max()) {
|
||||
return (uint8_t)result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -434,6 +434,14 @@ void CreatePushHashKey(const nsCString& scheme, const nsCString& hostHeader,
|
|||
uint64_t serial, const nsACString& pathInfo,
|
||||
nsCString& outOrigin, nsCString& outKey);
|
||||
|
||||
nsresult GetNSResultFromWebTransportError(uint8_t aErrorCode);
|
||||
|
||||
uint8_t GetWebTransportErrorFromNSResult(nsresult aResult);
|
||||
|
||||
uint64_t WebTransportErrorToHttp3Error(uint8_t aErrorCode);
|
||||
|
||||
uint8_t Http3ErrorToWebTransportError(uint64_t aErrorCode);
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
if (os == "mac") and debug: [TIMEOUT, OK]
|
||||
[TIMEOUT, OK, CRASH]
|
||||
[Abort client-created bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort server-initiated bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort unidirectional stream with WebTransportError]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Close and abort unidirectional stream]
|
||||
expected: FAIL
|
||||
|
||||
[Abort unidirectional stream with default error code]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[STOP_SENDING coming from server]
|
||||
expected: TIMEOUT
|
||||
|
@ -28,19 +28,19 @@
|
|||
[streams-close.https.any.html]
|
||||
expected: [OK, TIMEOUT]
|
||||
[Abort client-created bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort server-initiated bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort unidirectional stream with WebTransportError]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Close and abort unidirectional stream]
|
||||
expected: FAIL
|
||||
|
||||
[Abort unidirectional stream with default error code]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[STOP_SENDING coming from server]
|
||||
expected: TIMEOUT
|
||||
|
@ -55,19 +55,19 @@
|
|||
if (os == "mac") and debug: [TIMEOUT, OK]
|
||||
[TIMEOUT, OK, CRASH]
|
||||
[Abort client-created bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort server-initiated bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort unidirectional stream with WebTransportError]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Close and abort unidirectional stream]
|
||||
expected: FAIL
|
||||
|
||||
[Abort unidirectional stream with default error code]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[STOP_SENDING coming from server]
|
||||
expected: TIMEOUT
|
||||
|
@ -83,19 +83,19 @@
|
|||
if not fission: [TIMEOUT, OK, ERROR, CRASH]
|
||||
[TIMEOUT, OK, ERROR]
|
||||
[Abort client-created bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort server-initiated bidirectional stream]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Abort unidirectional stream with WebTransportError]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[Close and abort unidirectional stream]
|
||||
expected: FAIL
|
||||
|
||||
[Abort unidirectional stream with default error code]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[STOP_SENDING coming from server]
|
||||
expected: TIMEOUT
|
||||
|
|
|
@ -447,6 +447,11 @@ with modules["NETWORK"]:
|
|||
# Generic error for non-specific failures during service worker interception
|
||||
errors["NS_ERROR_INTERCEPTION_FAILED"] = FAILURE(100)
|
||||
|
||||
errors["NS_ERROR_WEBTRANSPORT_CODE_BASE"] = FAILURE(200)
|
||||
errors["NS_ERROR_WEBTRANSPORT_CODE_END"] = (
|
||||
errors["NS_ERROR_WEBTRANSPORT_CODE_BASE"] + 255
|
||||
)
|
||||
|
||||
# All Http proxy CONNECT response codes
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] = FAILURE(1000)
|
||||
# Redirection 3xx
|
||||
|
|
Загрузка…
Ссылка в новой задаче