bug 1081341 - h2 1xx responses r=hurley

This commit is contained in:
Patrick McManus 2014-09-27 09:06:38 -04:00
Родитель a0d8806209
Коммит aec785a65a
4 изменённых файлов: 33 добавлений и 32 удалений

Просмотреть файл

@ -884,26 +884,6 @@ Http2Compressor::EncodeHeaderBlock(const nsCString &nvInput,
int32_t valueIndex = colonIndex + 1;
// if we have Expect: *100-continue,*" redact the 100-continue
// as we don't have a good mechanism for clients to make use of it
// anyhow
if (name.EqualsLiteral("expect")) {
const char *continueHeader =
nsHttp::FindToken(beginBuffer + valueIndex, "100-continue",
HTTP_HEADER_VALUE_SEPS);
if (continueHeader) {
char *writableVal = const_cast<char *>(continueHeader);
memset(writableVal, 0, 12);
writableVal += 12;
// this will terminate safely because CRLF EOL has been confirmed
while ((*writableVal == ' ') || (*writableVal == '\t') ||
(*writableVal == ',')) {
*writableVal = ' ';
++writableVal;
}
}
}
while (valueIndex < crlfIndex && beginBuffer[valueIndex] == ' ')
++valueIndex;

Просмотреть файл

@ -1153,10 +1153,12 @@ Http2Session::RecvHeaders(Http2Session *self)
return NS_OK;
}
// make sure this is either the first headers or a trailer
if (self->mInputFrameDataStream->AllHeadersReceived() &&
!(self->mInputFrameFlags & kFlag_END_STREAM)) {
// Any header block after the first that does *not* end the stream is
// illegal.
LOG3(("Http2Session::Illegal Extra HeaderBlock %p 0x%X\n", self, self->mInputFrameID));
RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
}
@ -1192,7 +1194,7 @@ Http2Session::ResponseHeadersComplete()
LOG3(("Http2Session::ResponseHeadersComplete %p for 0x%X fin=%d",
this, mInputFrameDataStream->StreamID(), mInputFrameFinal));
// only interpret headers once, afterwards ignore trailers
// only interpret headers once, afterwards ignore as trailers
if (mInputFrameDataStream->AllHeadersReceived()) {
LOG3(("Http2Session::ResponseHeadersComplete extra headers"));
MOZ_ASSERT(mInputFrameFlags & kFlag_END_STREAM);
@ -1212,6 +1214,10 @@ Http2Session::ResponseHeadersComplete()
return NS_OK;
}
// if this turns out to be a 1xx response code we have to
// undo the headers received bit that we are setting here.
bool didFirstSetAllRecvd = !mInputFrameDataStream->AllHeadersReceived();
mInputFrameDataStream->SetAllHeadersReceived();
// The stream needs to see flattened http headers
@ -1220,10 +1226,12 @@ Http2Session::ResponseHeadersComplete()
// mFlatHTTPResponseHeaders via ConvertHeaders()
nsresult rv;
int32_t httpResponseCode; // out param to ConvertResponseHeaders
mFlatHTTPResponseHeadersOut = 0;
rv = mInputFrameDataStream->ConvertResponseHeaders(&mDecompressor,
mDecompressBuffer,
mFlatHTTPResponseHeaders);
mFlatHTTPResponseHeaders,
httpResponseCode);
if (rv == NS_ERROR_ABORT) {
LOG(("Http2Session::ResponseHeadersComplete ConvertResponseHeaders aborted\n"));
if (mInputFrameDataStream->IsTunnel()) {
@ -1238,6 +1246,11 @@ Http2Session::ResponseHeadersComplete()
return rv;
}
// allow more headers in the case of 1xx
if (((httpResponseCode / 100) == 1) && didFirstSetAllRecvd) {
mInputFrameDataStream->UnsetAllHeadersReceived();
}
ChangeDownstreamState(PROCESSING_COMPLETE_HEADERS);
return NS_OK;
}

Просмотреть файл

@ -840,7 +840,8 @@ Http2Stream::GenerateDataFrameHeader(uint32_t dataLength, bool lastFrame)
nsresult
Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor,
nsACString &aHeadersIn,
nsACString &aHeadersOut)
nsACString &aHeadersOut,
int32_t &httpResponseCode)
{
aHeadersOut.Truncate();
aHeadersOut.SetCapacity(aHeadersIn.Length() + 512);
@ -854,23 +855,28 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor,
return NS_ERROR_ILLEGAL_VALUE;
}
nsAutoCString status;
decompressor->GetStatus(status);
if (status.IsEmpty()) {
nsAutoCString statusString;
decompressor->GetStatus(statusString);
if (statusString.IsEmpty()) {
LOG3(("Http2Stream::ConvertHeaders %p Error - no status\n", this));
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult errcode;
httpResponseCode = statusString.ToInteger(&errcode);
if (mIsTunnel) {
nsresult errcode;
int32_t code = status.ToInteger(&errcode);
LOG3(("Http2Stream %p Tunnel Response code %d", this, code));
if ((code / 100) != 2) {
LOG3(("Http2Stream %p Tunnel Response code %d", this, httpResponseCode));
if ((httpResponseCode / 100) != 2) {
MapStreamToPlainText();
}
}
if (httpResponseCode == 101) {
// 8.1.1 of h2 disallows 101.. throw PROTOCOL_ERROR on stream
LOG3(("Http2Stream::ConvertHeaders %p Error - status == 101\n", this));
return NS_ERROR_ILLEGAL_VALUE;
}
if (aHeadersIn.Length() && aHeadersOut.Length()) {
Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_SIZE, aHeadersIn.Length());
uint32_t ratio =

Просмотреть файл

@ -85,13 +85,15 @@ public:
bool CountAsActive() { return mCountAsActive; }
void SetAllHeadersReceived();
void UnsetAllHeadersReceived() { mAllHeadersReceived = 0; }
bool AllHeadersReceived() { return mAllHeadersReceived; }
void UpdateTransportSendEvents(uint32_t count);
void UpdateTransportReadEvents(uint32_t count);
// NS_ERROR_ABORT terminates stream, other failure terminates session
nsresult ConvertResponseHeaders(Http2Decompressor *, nsACString &, nsACString &);
nsresult ConvertResponseHeaders(Http2Decompressor *, nsACString &,
nsACString &, int32_t &);
nsresult ConvertPushHeaders(Http2Decompressor *, nsACString &, nsACString &);
bool AllowFlowControlledWrite();