Bug 1429973 part 1 - plumb through trailers in h2 to support server-timing. r=bagder

MozReview-Commit-ID: JV1Ikb9cYCV

--HG--
extra : rebase_source : fa67fef606fc02355579dae42f8e66c4754d60a0
This commit is contained in:
Nicholas Hurley 2018-02-01 15:14:23 -08:00
parent d956bcaac3
commit be1b7537f2
5 changed files with 84 additions and 7 deletions

View File

@ -1433,13 +1433,16 @@ Http2Session::ResponseHeadersComplete()
LOG3(("Http2Session::ResponseHeadersComplete %p for 0x%X fin=%d",
this, mInputFrameDataStream->StreamID(), mInputFrameFinal));
// only interpret headers once, afterwards ignore as trailers
// Anything prior to AllHeadersReceived() => true is actual headers. After
// that, we need to handle them as trailers instead (which are special-cased
// so we don't have to use the nasty chunked parser for all h2, just in case).
if (mInputFrameDataStream->AllHeadersReceived()) {
LOG3(("Http2Session::ResponseHeadersComplete extra headers"));
LOG3(("Http2Session::ResponseHeadersComplete processing trailers"));
MOZ_ASSERT(mInputFrameFlags & kFlag_END_STREAM);
nsresult rv = UncompressAndDiscard(false);
nsresult rv = mInputFrameDataStream->ConvertResponseTrailers(&mDecompressor,
mDecompressBuffer);
if (NS_FAILED(rv)) {
LOG3(("Http2Session::ResponseHeadersComplete extra uncompress failed\n"));
LOG3(("Http2Session::ResponseHeadersComplete trailer conversion failed\n"));
return rv;
}
mFlatHTTPResponseHeadersOut = 0;

View File

@ -1023,6 +1023,8 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor,
int32_t &httpResponseCode)
{
aHeadersOut.Truncate();
// Add in some space to hopefully not have to reallocate while decompressing
// the headers. 512 bytes seems like a good enough number.
aHeadersOut.SetCapacity(aHeadersIn.Length() + 512);
nsresult rv =
@ -1106,6 +1108,8 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor,
nsACString &aHeadersOut)
{
aHeadersOut.Truncate();
// Add in some space to hopefully not have to reallocate while decompressing
// the headers. 512 bytes seems like a good enough number.
aHeadersOut.SetCapacity(aHeadersIn.Length() + 512);
nsresult rv =
decompressor->DecodeHeaderBlock(reinterpret_cast<const uint8_t *>(aHeadersIn.BeginReading()),
@ -1142,6 +1146,35 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor,
return NS_OK;
}
nsresult
Http2Stream::ConvertResponseTrailers(Http2Decompressor *decompressor,
nsACString &aTrailersIn)
{
LOG3(("Http2Stream::ConvertResponseTrailers %p", this));
nsAutoCString flatTrailers;
// Add in some space to hopefully not have to reallocate while decompressing
// the headers. 512 bytes seems like a good enough number.
flatTrailers.SetCapacity(aTrailersIn.Length() + 512);
nsresult rv =
decompressor->DecodeHeaderBlock(reinterpret_cast<const uint8_t *>(aTrailersIn.BeginReading()),
aTrailersIn.Length(),
flatTrailers, false);
if (NS_FAILED(rv)) {
LOG3(("Http2Stream::ConvertResponseTrailers %p decode Error", this));
return rv;
}
nsHttpTransaction *trans = mTransaction->QueryHttpTransaction();
if (trans) {
trans->SetHttpTrailers(flatTrailers);
} else {
LOG3(("Http2Stream::ConvertResponseTrailers %p no trans", this));
}
return NS_OK;
}
void
Http2Stream::Close(nsresult reason)
{

View File

@ -125,6 +125,8 @@ public:
nsACString &, int32_t &);
MOZ_MUST_USE nsresult ConvertPushHeaders(Http2Decompressor *, nsACString &,
nsACString &);
MOZ_MUST_USE nsresult ConvertResponseTrailers(Http2Decompressor *,
nsACString &);
bool AllowFlowControlledWrite();
void UpdateServerReceiveWindow(int32_t delta);

View File

@ -1782,9 +1782,9 @@ nsHttpTransaction::HandleContent(char *buf,
if ((mContentRead == mContentLength) ||
(mChunkedDecoder && mChunkedDecoder->ReachedEOF())) {
MutexAutoLock lock(*nsHttp::GetLock());
mForTakeResponseTrailers = mChunkedDecoder
? mChunkedDecoder->TakeTrailers()
: nullptr;
if (mChunkedDecoder) {
mForTakeResponseTrailers = mChunkedDecoder->TakeTrailers();
}
// the transaction is done with a complete response.
mTransactionDone = true;
@ -2438,5 +2438,42 @@ nsHttpTransaction::Refused0RTT()
}
}
void
nsHttpTransaction::SetHttpTrailers(nsCString &aTrailers)
{
LOG(("nsHttpTransaction::SetHttpTrailers %p", this));
LOG(("[\n %s\n]", aTrailers.BeginReading()));
if (!mForTakeResponseTrailers) {
mForTakeResponseTrailers = new nsHttpHeaderArray();
}
int32_t cur = 0;
int32_t len = aTrailers.Length();
while (cur < len) {
int32_t newline = aTrailers.FindCharInSet("\n", cur);
if (newline == -1) {
newline = len;
}
int32_t end = aTrailers[newline - 1] == '\r' ? newline - 1 : newline;
nsDependentCSubstring line(aTrailers, cur, end);
nsHttpAtom hdr = {nullptr};
nsAutoCString hdrNameOriginal;
nsAutoCString val;
if (NS_SUCCEEDED(mForTakeResponseTrailers->ParseHeaderLine(line, &hdr, &hdrNameOriginal, &val))) {
if (hdr == nsHttp::Server_Timing) {
Unused << mForTakeResponseTrailers->SetHeaderFromNet(hdr, hdrNameOriginal, val, true);
}
}
cur = newline + 1;
}
if (mForTakeResponseTrailers->Count() == 0) {
// Didn't find a Server-Timing header, so get rid of this.
mForTakeResponseTrailers = nullptr;
}
}
} // namespace net
} // namespace mozilla

View File

@ -191,6 +191,8 @@ public:
}
void SetFastOpenStatus(uint8_t aStatus) override;
void SetHttpTrailers(nsCString &aTrailers);
private:
friend class DeleteHttpTransaction;
virtual ~nsHttpTransaction();