From 9dddba61a2dd4d62408dea4b190b044101b664e9 Mon Sep 17 00:00:00 2001 From: Nicholas Hurley Date: Fri, 27 Jun 2014 13:13:42 -0700 Subject: [PATCH] Bug 1030203 - Send PROTOCOL_ERROR when receiving PUSH_PROMISE with push disabled. r=mcmanus --- netwerk/protocol/http/Http2Session.cpp | 15 +++++++++++++-- netwerk/protocol/http/Http2Session.h | 7 +++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp index dd06f04fd7a..1154eb2e109 100644 --- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -98,6 +98,8 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport) , mOutputQueueSent(0) , mLastReadEpoch(PR_IntervalNow()) , mPingSentEpoch(0) + , mWaitingForSettingsAck(false) + , mGoAwayOnPush(false) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -808,6 +810,8 @@ Http2Session::SendHello() CopyAsNetwork16(packet + 8 + (6 * numberOfEntries), SETTINGS_TYPE_MAX_CONCURRENT); // The value portion of the setting pair is already initialized to 0 numberOfEntries++; + + mWaitingForSettingsAck = true; } // Advertise the Push RWIN for the session, and on each new pull stream @@ -1359,8 +1363,11 @@ Http2Session::RecvSettings(Http2Session *self) self->ResetDownstreamState(); - if (!(self->mInputFrameFlags & kFlag_ACK)) + if (!(self->mInputFrameFlags & kFlag_ACK)) { self->GenerateSettingsAck(); + } else if (self->mWaitingForSettingsAck) { + self->mGoAwayOnPush = true; + } return NS_OK; } @@ -1444,8 +1451,12 @@ Http2Session::RecvPushPromise(Http2Session *self) "mode refused.\n", self)); self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID); } else if (!gHttpHandler->AllowPush()) { - // MAX_CONCURRENT_STREAMS of 0 in settings disabled push + // ENABLE_PUSH and MAX_CONCURRENT_STREAMS of 0 in settings disabled push LOG3(("Http2Session::RecvPushPromise Push Recevied when Disabled\n")); + if (self->mGoAwayOnPush) { + LOG3(("Http2Session::RecvPushPromise sending GOAWAY")); + RETURN_SESSION_ERROR(self, PROTOCOL_ERROR); + } self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID); } else if (!(self->mInputFrameFlags & kFlag_END_PUSH_PROMISE)) { LOG3(("Http2Session::RecvPushPromise no support for multi frame push\n")); diff --git a/netwerk/protocol/http/Http2Session.h b/netwerk/protocol/http/Http2Session.h index 27509947631..87b556c6a79 100644 --- a/netwerk/protocol/http/Http2Session.h +++ b/netwerk/protocol/http/Http2Session.h @@ -441,6 +441,13 @@ private: // to make sure streams aren't shared across sessions. uint64_t mSerial; + // If push is disabled, we want to be able to send PROTOCOL_ERRORs if we + // receive a PUSH_PROMISE, but we have to wait for the SETTINGS ACK before + // we can actually tell the other end to go away. These help us keep track + // of that state so we can behave appropriately. + bool mWaitingForSettingsAck; + bool mGoAwayOnPush; + private: /// connect tunnels void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);