mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 1097944 - remove spdy/3 2/2 r=hurley
This commit is contained in:
parent
b027d2409d
commit
5f7fc6a565
@ -1271,7 +1271,6 @@ pref("network.http.bypass-cachelock-threshold", 250);
|
||||
|
||||
// Try and use SPDY when using SSL
|
||||
pref("network.http.spdy.enabled", true);
|
||||
pref("network.http.spdy.enabled.v3", true);
|
||||
pref("network.http.spdy.enabled.v3-1", true);
|
||||
pref("network.http.spdy.enabled.http2draft", true);
|
||||
pref("network.http.spdy.enabled.http2", false);
|
||||
|
@ -778,9 +778,7 @@ HttpConnInfo::SetHTTP1ProtocolVersion(uint8_t pv)
|
||||
void
|
||||
HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
|
||||
{
|
||||
if (pv == SPDY_VERSION_3) {
|
||||
protocolVersion.AssignLiteral(MOZ_UTF16("spdy/3"));
|
||||
} else if (pv == SPDY_VERSION_31) {
|
||||
if (pv == SPDY_VERSION_31) {
|
||||
protocolVersion.AssignLiteral(MOZ_UTF16("spdy/3.1"));
|
||||
} else if (pv == NS_HTTP2_DRAFT_VERSION) {
|
||||
MOZ_ASSERT (pv == NS_HTTP2_DRAFT_VERSION);
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "HttpLog.h"
|
||||
|
||||
/*
|
||||
Currently supported are HTTP-draft-[see nshttp.h]/2.0 spdy/3.1 and spdy/3
|
||||
Currently supported are HTTP-draft-[see nshttp.h]/2.0 spdy/3.1
|
||||
*/
|
||||
|
||||
#include "nsHttp.h"
|
||||
@ -16,10 +16,8 @@
|
||||
|
||||
#include "ASpdySession.h"
|
||||
#include "PSpdyPush.h"
|
||||
#include "SpdyPush3.h"
|
||||
#include "SpdyPush31.h"
|
||||
#include "Http2Push.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdySession31.h"
|
||||
#include "Http2Session.h"
|
||||
|
||||
@ -42,8 +40,7 @@ ASpdySession::NewSpdySession(uint32_t version,
|
||||
{
|
||||
// This is a necko only interface, so we can enforce version
|
||||
// requests as a precondition
|
||||
MOZ_ASSERT(version == SPDY_VERSION_3 ||
|
||||
version == SPDY_VERSION_31 ||
|
||||
MOZ_ASSERT(version == SPDY_VERSION_31 ||
|
||||
version == HTTP_VERSION_2 ||
|
||||
version == NS_HTTP2_DRAFT_VERSION,
|
||||
"Unsupported spdy version");
|
||||
@ -55,11 +52,9 @@ ASpdySession::NewSpdySession(uint32_t version,
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SPDY_VERSION2, version);
|
||||
|
||||
if (version == SPDY_VERSION_3) {
|
||||
return new SpdySession3(aTransport);
|
||||
} else if (version == SPDY_VERSION_31) {
|
||||
if (version == SPDY_VERSION_31) {
|
||||
return new SpdySession31(aTransport);
|
||||
} else if (version == NS_HTTP2_DRAFT_VERSION || version == HTTP_VERSION_2) {
|
||||
} else if (version == NS_HTTP2_DRAFT_VERSION || version == HTTP_VERSION_2) {
|
||||
return new Http2Session(aTransport);
|
||||
}
|
||||
|
||||
@ -74,25 +69,21 @@ SpdyInformation::SpdyInformation()
|
||||
{
|
||||
// highest index of enabled protocols is the
|
||||
// most preferred for ALPN negotiaton
|
||||
Version[0] = SPDY_VERSION_3;
|
||||
VersionString[0] = NS_LITERAL_CSTRING("spdy/3");
|
||||
Version[0] = SPDY_VERSION_31;
|
||||
VersionString[0] = NS_LITERAL_CSTRING("spdy/3.1");
|
||||
ALPNCallbacks[0] = SpdySessionTrue;
|
||||
|
||||
Version[1] = SPDY_VERSION_31;
|
||||
VersionString[1] = NS_LITERAL_CSTRING("spdy/3.1");
|
||||
ALPNCallbacks[1] = SpdySessionTrue;
|
||||
Version[1] = HTTP_VERSION_2;
|
||||
VersionString[1] = NS_LITERAL_CSTRING("h2");
|
||||
ALPNCallbacks[1] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[2] = HTTP_VERSION_2;
|
||||
VersionString[2] = NS_LITERAL_CSTRING("h2");
|
||||
Version[2] = NS_HTTP2_DRAFT_VERSION;
|
||||
VersionString[2] = NS_LITERAL_CSTRING("h2-14");
|
||||
ALPNCallbacks[2] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[3] = NS_HTTP2_DRAFT_VERSION;
|
||||
VersionString[3] = NS_LITERAL_CSTRING("h2-14");
|
||||
VersionString[3] = NS_LITERAL_CSTRING(NS_HTTP2_DRAFT_TOKEN);
|
||||
ALPNCallbacks[3] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[4] = NS_HTTP2_DRAFT_VERSION;
|
||||
VersionString[4] = NS_LITERAL_CSTRING(NS_HTTP2_DRAFT_TOKEN);
|
||||
ALPNCallbacks[4] = Http2Session::ALPNCallback;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -102,13 +93,11 @@ SpdyInformation::ProtocolEnabled(uint32_t index) const
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
return gHttpHandler->IsSpdyV3Enabled();
|
||||
case 1:
|
||||
return gHttpHandler->IsSpdyV31Enabled();
|
||||
case 2:
|
||||
case 1:
|
||||
return gHttpHandler->IsHttp2Enabled();
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return gHttpHandler->IsHttp2DraftEnabled();
|
||||
}
|
||||
return false;
|
||||
@ -141,37 +130,10 @@ SpdyPushCache::SpdyPushCache()
|
||||
|
||||
SpdyPushCache::~SpdyPushCache()
|
||||
{
|
||||
mHashSpdy3.Clear();
|
||||
mHashSpdy31.Clear();
|
||||
mHashHttp2.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushCache::RegisterPushedStreamSpdy3(nsCString key,
|
||||
SpdyPushedStream3 *stream)
|
||||
{
|
||||
LOG3(("SpdyPushCache::RegisterPushedStreamSpdy3 %s 0x%X\n",
|
||||
key.get(), stream->StreamID()));
|
||||
if(mHashSpdy3.Get(key)) {
|
||||
LOG3(("SpdyPushCache::RegisterPushedStreamSpdy3 %s 0x%X duplicate key\n",
|
||||
key.get(), stream->StreamID()));
|
||||
return false;
|
||||
}
|
||||
mHashSpdy3.Put(key, stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
SpdyPushedStream3 *
|
||||
SpdyPushCache::RemovePushedStreamSpdy3(nsCString key)
|
||||
{
|
||||
SpdyPushedStream3 *rv = mHashSpdy3.Get(key);
|
||||
LOG3(("SpdyPushCache::RemovePushedStream %s 0x%X\n",
|
||||
key.get(), rv ? rv->StreamID() : 0));
|
||||
if (rv)
|
||||
mHashSpdy3.Remove(key);
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushCache::RegisterPushedStreamSpdy31(nsCString key,
|
||||
SpdyPushedStream31 *stream)
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
SpdyInformation();
|
||||
~SpdyInformation() {}
|
||||
|
||||
static const uint32_t kCount = 5;
|
||||
static const uint32_t kCount = 4;
|
||||
|
||||
// determine the index (0..kCount-1) of the spdy information that
|
||||
// correlates to the npn string. NS_FAILED() if no match is found.
|
||||
|
@ -189,8 +189,7 @@ public:
|
||||
// insist on spdy/3* or >= http/2
|
||||
uint32_t version = mConnection->Version();
|
||||
LOG(("AltSvcTransaction::MaybeValidate() %p version %d\n", this, version));
|
||||
if ((version < HTTP_VERSION_2) &&
|
||||
(version != SPDY_VERSION_31) && (version != SPDY_VERSION_3)) {
|
||||
if ((version < HTTP_VERSION_2) && (version != SPDY_VERSION_31)) {
|
||||
LOG(("AltSvcTransaction::MaybeValidate %p Failed due to protocol version", this));
|
||||
return;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "nsHttpConnectionMgr.h"
|
||||
#include "nsHttpConnection.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdySession31.h"
|
||||
#include "Http2Session.h"
|
||||
#include "nsHttpHandler.h"
|
||||
@ -161,44 +160,6 @@ nsHttpConnection::PrintDiagnostics(nsCString &log)
|
||||
mSpdySession->PrintDiagnostics(log);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpdySession3::PrintDiagnostics(nsCString &log)
|
||||
{
|
||||
log.AppendPrintf(" ::: SPDY VERSION 3\n");
|
||||
log.AppendPrintf(" shouldgoaway = %d mClosed = %d CanReuse = %d nextID=0x%X\n",
|
||||
mShouldGoAway, mClosed, CanReuse(), mNextStreamID);
|
||||
|
||||
log.AppendPrintf(" concurrent = %d maxconcurrent = %d\n",
|
||||
mConcurrent, mMaxConcurrent);
|
||||
|
||||
log.AppendPrintf(" roomformorestreams = %d roomformoreconcurrent = %d\n",
|
||||
RoomForMoreStreams(), RoomForMoreConcurrent());
|
||||
|
||||
log.AppendPrintf(" transactionHashCount = %d streamIDHashCount = %d\n",
|
||||
mStreamTransactionHash.Count(),
|
||||
mStreamIDHash.Count());
|
||||
|
||||
log.AppendPrintf(" Queued Stream Size = %d\n", mQueuedStreams.GetSize());
|
||||
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
log.AppendPrintf(" Ping Threshold = %ums next ping id = 0x%X\n",
|
||||
PR_IntervalToMilliseconds(mPingThreshold),
|
||||
mNextPingID);
|
||||
log.AppendPrintf(" Ping Timeout = %ums\n",
|
||||
PR_IntervalToMilliseconds(gHttpHandler->SpdyPingTimeout()));
|
||||
log.AppendPrintf(" Idle for Any Activity (ping) = %ums\n",
|
||||
PR_IntervalToMilliseconds(now - mLastReadEpoch));
|
||||
log.AppendPrintf(" Idle for Data Activity = %ums\n",
|
||||
PR_IntervalToMilliseconds(now - mLastDataReadEpoch));
|
||||
if (mPingSentEpoch)
|
||||
log.AppendPrintf(" Ping Outstanding (ping) = %ums, expired = %d\n",
|
||||
PR_IntervalToMilliseconds(now - mPingSentEpoch),
|
||||
now - mPingSentEpoch >= gHttpHandler->SpdyPingTimeout());
|
||||
else
|
||||
log.AppendPrintf(" No Ping Outstanding\n");
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession31::PrintDiagnostics(nsCString &log)
|
||||
{
|
||||
|
@ -34,7 +34,6 @@ class nsCString;
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class SpdyPushedStream3;
|
||||
class SpdyPushedStream31;
|
||||
class Http2PushedStream;
|
||||
|
||||
@ -46,15 +45,6 @@ public:
|
||||
SpdyPushCache();
|
||||
virtual ~SpdyPushCache();
|
||||
|
||||
// for spdy/3
|
||||
public:
|
||||
bool RegisterPushedStreamSpdy3(nsCString key,
|
||||
SpdyPushedStream3 *stream);
|
||||
SpdyPushedStream3 *RemovePushedStreamSpdy3(nsCString key);
|
||||
|
||||
private:
|
||||
nsDataHashtable<nsCStringHashKey, SpdyPushedStream3 *> mHashSpdy3;
|
||||
|
||||
// for spdy/3.1
|
||||
public:
|
||||
bool RegisterPushedStreamSpdy31(nsCString key,
|
||||
|
@ -1,379 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// HttpLog.h should generally be included first
|
||||
#include "HttpLog.h"
|
||||
|
||||
// Log on level :5, instead of default :4.
|
||||
#undef LOG
|
||||
#define LOG(args) LOG5(args)
|
||||
#undef LOG_ENABLED
|
||||
#define LOG_ENABLED() LOG5_ENABLED()
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "SpdyPush3.h"
|
||||
#include "PSpdyPush.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "nsHttpRequestHead.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPushedStream3
|
||||
//////////////////////////////////////////
|
||||
|
||||
SpdyPushedStream3::SpdyPushedStream3(SpdyPush3TransactionBuffer *aTransaction,
|
||||
SpdySession3 *aSession,
|
||||
SpdyStream3 *aAssociatedStream,
|
||||
uint32_t aID)
|
||||
:SpdyStream3(aTransaction, aSession,
|
||||
0 /* priority is only for sending, so ignore it on push */)
|
||||
, mConsumerStream(nullptr)
|
||||
, mBufferedPush(aTransaction)
|
||||
, mStatus(NS_OK)
|
||||
, mPushCompleted(false)
|
||||
, mDeferCleanupOnSuccess(true)
|
||||
{
|
||||
LOG3(("SpdyPushedStream3 ctor this=%p 0x%X\n", this, aID));
|
||||
mStreamID = aID;
|
||||
mBufferedPush->SetPushStream(this);
|
||||
mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
|
||||
mLastRead = TimeStamp::Now();
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream3::GetPushComplete()
|
||||
{
|
||||
return mPushCompleted;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPushedStream3::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
uint32_t count,
|
||||
uint32_t *countWritten)
|
||||
{
|
||||
nsresult rv = SpdyStream3::WriteSegments(writer, count, countWritten);
|
||||
if (NS_SUCCEEDED(rv) && *countWritten) {
|
||||
mLastRead = TimeStamp::Now();
|
||||
}
|
||||
|
||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||
mPushCompleted = true;
|
||||
rv = NS_OK; // this is what a normal HTTP transaction would do
|
||||
}
|
||||
if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv))
|
||||
mStatus = rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPushedStream3::ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *count)
|
||||
{
|
||||
// The SYN_STREAM for this has been processed, so we need to verify
|
||||
// that :host, :scheme, and :path MUST be present
|
||||
nsDependentCSubstring host, scheme, path;
|
||||
nsresult rv;
|
||||
|
||||
rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":host"), host);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
|
||||
"push without required :host\n", mSession, mStreamID));
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":scheme"), scheme);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
|
||||
"push without required :scheme\n", mSession, mStreamID));
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":path"), path);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
|
||||
"push without required :host\n", mSession, mStreamID));
|
||||
return rv;
|
||||
}
|
||||
|
||||
CreatePushHashKey(nsCString(scheme), nsCString(host),
|
||||
mSession->Serial(), path,
|
||||
mOrigin, mHashKey);
|
||||
|
||||
LOG3(("SpdyPushStream3 0x%X hash key %s\n", mStreamID, mHashKey.get()));
|
||||
|
||||
// the write side of a pushed transaction just involves manipulating a little state
|
||||
SpdyStream3::mSentFinOnData = 1;
|
||||
SpdyStream3::mSynFrameComplete = 1;
|
||||
SpdyStream3::ChangeState(UPSTREAM_COMPLETE);
|
||||
*count = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream3::GetHashKey(nsCString &key)
|
||||
{
|
||||
if (mHashKey.IsEmpty())
|
||||
return false;
|
||||
|
||||
key = mHashKey;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPushedStream3::ConnectPushedStream(SpdyStream3 *stream)
|
||||
{
|
||||
mSession->ConnectPushedStream(stream);
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream3::IsOrphaned(TimeStamp now)
|
||||
{
|
||||
MOZ_ASSERT(!now.IsNull());
|
||||
|
||||
// if spdy is not transmitting, and is also not connected to a consumer
|
||||
// stream, and its been like that for too long then it is oprhaned
|
||||
|
||||
if (mConsumerStream)
|
||||
return false;
|
||||
|
||||
bool rv = ((now - mLastRead).ToSeconds() > 30.0);
|
||||
if (rv) {
|
||||
LOG3(("SpdyPushCache::IsOrphaned 0x%X IsOrphaned %3.2f\n",
|
||||
mStreamID, (now - mLastRead).ToSeconds()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPushedStream3::GetBufferedData(char *buf,
|
||||
uint32_t count,
|
||||
uint32_t *countWritten)
|
||||
{
|
||||
if (NS_FAILED(mStatus))
|
||||
return mStatus;
|
||||
|
||||
nsresult rv = mBufferedPush->GetBufferedData(buf, count, countWritten);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!*countWritten)
|
||||
rv = GetPushComplete() ? NS_BASE_STREAM_CLOSED : NS_BASE_STREAM_WOULD_BLOCK;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPush3TransactionBuffer
|
||||
// This is the nsAHttpTransction owned by the stream when the pushed
|
||||
// stream has not yet been matched with a pull request
|
||||
//////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS0(SpdyPush3TransactionBuffer)
|
||||
|
||||
SpdyPush3TransactionBuffer::SpdyPush3TransactionBuffer()
|
||||
: mStatus(NS_OK)
|
||||
, mRequestHead(nullptr)
|
||||
, mPushStream(nullptr)
|
||||
, mIsDone(false)
|
||||
, mBufferedHTTP1Size(kDefaultBufferSize)
|
||||
, mBufferedHTTP1Used(0)
|
||||
, mBufferedHTTP1Consumed(0)
|
||||
{
|
||||
mBufferedHTTP1 = new char[mBufferedHTTP1Size];
|
||||
}
|
||||
|
||||
SpdyPush3TransactionBuffer::~SpdyPush3TransactionBuffer()
|
||||
{
|
||||
delete mRequestHead;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::SetConnection(nsAHttpConnection *conn)
|
||||
{
|
||||
}
|
||||
|
||||
nsAHttpConnection *
|
||||
SpdyPush3TransactionBuffer::Connection()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
|
||||
{
|
||||
*outCB = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::OnTransportStatus(nsITransport* transport,
|
||||
nsresult status, uint64_t progress)
|
||||
{
|
||||
}
|
||||
|
||||
nsHttpConnectionInfo *
|
||||
SpdyPush3TransactionBuffer::ConnectionInfo()
|
||||
{
|
||||
if (!mPushStream) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!mPushStream->Transaction()) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(mPushStream->Transaction() != this);
|
||||
return mPushStream->Transaction()->ConnectionInfo();
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPush3TransactionBuffer::IsDone()
|
||||
{
|
||||
return mIsDone;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::Status()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush3TransactionBuffer::Caps()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::SetDNSWasRefreshed()
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t
|
||||
SpdyPush3TransactionBuffer::Available()
|
||||
{
|
||||
return mBufferedHTTP1Used - mBufferedHTTP1Consumed;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::ReadSegments(nsAHttpSegmentReader *reader,
|
||||
uint32_t count, uint32_t *countRead)
|
||||
{
|
||||
*countRead = 0;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
uint32_t count, uint32_t *countWritten)
|
||||
{
|
||||
if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
|
||||
EnsureBuffer(mBufferedHTTP1, mBufferedHTTP1Size + kDefaultBufferSize,
|
||||
mBufferedHTTP1Used, mBufferedHTTP1Size);
|
||||
}
|
||||
|
||||
count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
|
||||
nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
|
||||
count, countWritten);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mBufferedHTTP1Used += *countWritten;
|
||||
}
|
||||
else if (rv == NS_BASE_STREAM_CLOSED) {
|
||||
mIsDone = true;
|
||||
}
|
||||
|
||||
if (Available()) {
|
||||
SpdyStream3 *consumer = mPushStream->GetConsumerStream();
|
||||
|
||||
if (consumer) {
|
||||
LOG3(("SpdyPush3TransactionBuffer::WriteSegments notifying connection "
|
||||
"consumer data available 0x%X [%u]\n",
|
||||
mPushStream->StreamID(), Available()));
|
||||
mPushStream->ConnectPushedStream(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush3TransactionBuffer::Http1xTransactionCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsHttpRequestHead *
|
||||
SpdyPush3TransactionBuffer::RequestHead()
|
||||
{
|
||||
if (!mRequestHead)
|
||||
mRequestHead = new nsHttpRequestHead();
|
||||
return mRequestHead;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::SetProxyConnectFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush3TransactionBuffer::Close(nsresult reason)
|
||||
{
|
||||
mStatus = reason;
|
||||
mIsDone = true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::AddTransaction(nsAHttpTransaction *trans)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush3TransactionBuffer::PipelineDepth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::SetPipelinePosition(int32_t position)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t
|
||||
SpdyPush3TransactionBuffer::PipelinePosition()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush3TransactionBuffer::GetBufferedData(char *buf,
|
||||
uint32_t count,
|
||||
uint32_t *countWritten)
|
||||
{
|
||||
*countWritten = std::min(count, static_cast<uint32_t>(Available()));
|
||||
if (*countWritten) {
|
||||
memcpy(buf, mBufferedHTTP1 + mBufferedHTTP1Consumed, *countWritten);
|
||||
mBufferedHTTP1Consumed += *countWritten;
|
||||
}
|
||||
|
||||
// If all the data has been consumed then reset the buffer
|
||||
if (mBufferedHTTP1Consumed == mBufferedHTTP1Used) {
|
||||
mBufferedHTTP1Consumed = 0;
|
||||
mBufferedHTTP1Used = 0;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
@ -1,102 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// SPDY Server Push as defined by
|
||||
// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
|
||||
|
||||
#ifndef mozilla_net_SpdyPush3_Internal_h
|
||||
#define mozilla_net_SpdyPush3_Internal_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsString.h"
|
||||
#include "SpdyStream3.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class SpdySession3;
|
||||
|
||||
class SpdyPush3TransactionBuffer;
|
||||
|
||||
class SpdyPushedStream3 MOZ_FINAL : public SpdyStream3
|
||||
{
|
||||
public:
|
||||
SpdyPushedStream3(SpdyPush3TransactionBuffer *aTransaction,
|
||||
SpdySession3 *aSession,
|
||||
SpdyStream3 *aAssociatedStream,
|
||||
uint32_t aID);
|
||||
virtual ~SpdyPushedStream3() {}
|
||||
|
||||
bool GetPushComplete();
|
||||
SpdyStream3 *GetConsumerStream() { return mConsumerStream; };
|
||||
void SetConsumerStream(SpdyStream3 *aStream) { mConsumerStream = aStream; }
|
||||
bool GetHashKey(nsCString &key);
|
||||
|
||||
// override of SpdyStream3
|
||||
nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *);
|
||||
nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *);
|
||||
|
||||
nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() { return mLoadGroupCI; };
|
||||
void ConnectPushedStream(SpdyStream3 *consumer);
|
||||
|
||||
bool DeferCleanupOnSuccess() { return mDeferCleanupOnSuccess; }
|
||||
void SetDeferCleanupOnSuccess(bool val) { mDeferCleanupOnSuccess = val; }
|
||||
|
||||
bool IsOrphaned(TimeStamp now);
|
||||
|
||||
nsresult GetBufferedData(char *buf, uint32_t count, uint32_t *countWritten);
|
||||
|
||||
// overload of SpdyStream3
|
||||
virtual bool HasSink() { return !!mConsumerStream; }
|
||||
|
||||
private:
|
||||
|
||||
SpdyStream3 *mConsumerStream; // paired request stream that consumes from
|
||||
// real spdy one.. null until a match is made.
|
||||
|
||||
nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
|
||||
|
||||
SpdyPush3TransactionBuffer *mBufferedPush;
|
||||
TimeStamp mLastRead;
|
||||
|
||||
nsCString mHashKey;
|
||||
nsresult mStatus;
|
||||
bool mPushCompleted; // server push FIN received
|
||||
bool mDeferCleanupOnSuccess;
|
||||
};
|
||||
|
||||
class SpdyPush3TransactionBuffer MOZ_FINAL : public nsAHttpTransaction
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
|
||||
SpdyPush3TransactionBuffer();
|
||||
|
||||
nsresult GetBufferedData(char *buf, uint32_t count, uint32_t *countWritten);
|
||||
void SetPushStream(SpdyPushedStream3 *stream) { mPushStream = stream; }
|
||||
|
||||
private:
|
||||
virtual ~SpdyPush3TransactionBuffer();
|
||||
|
||||
const static uint32_t kDefaultBufferSize = 4096;
|
||||
|
||||
nsresult mStatus;
|
||||
nsHttpRequestHead *mRequestHead;
|
||||
SpdyPushedStream3 *mPushStream;
|
||||
bool mIsDone;
|
||||
|
||||
nsAutoArrayPtr<char> mBufferedHTTP1;
|
||||
uint32_t mBufferedHTTP1Size;
|
||||
uint32_t mBufferedHTTP1Used;
|
||||
uint32_t mBufferedHTTP1Consumed;
|
||||
};
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_SpdyPush3_Internal_h
|
File diff suppressed because it is too large
Load Diff
@ -1,406 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_SpdySession3_h
|
||||
#define mozilla_net_SpdySession3_h
|
||||
|
||||
// SPDY as defined by
|
||||
// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
|
||||
|
||||
#include "ASpdySession.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAHttpConnection.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "zlib.h"
|
||||
|
||||
class nsISocketTransport;
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class SpdyPushedStream3;
|
||||
class SpdyStream3;
|
||||
class nsHttpTransaction;
|
||||
|
||||
class SpdySession3 MOZ_FINAL : public ASpdySession
|
||||
, public nsAHttpConnection
|
||||
, public nsAHttpSegmentReader
|
||||
, public nsAHttpSegmentWriter
|
||||
{
|
||||
~SpdySession3();
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
NS_DECL_NSAHTTPCONNECTION(mConnection)
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
|
||||
explicit SpdySession3(nsISocketTransport *);
|
||||
|
||||
bool AddStream(nsAHttpTransaction *, int32_t,
|
||||
bool, nsIInterfaceRequestor *);
|
||||
bool CanReuse() { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams();
|
||||
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
// have this invoked. It might happen sooner depending on the needs of
|
||||
// other connections.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now);
|
||||
|
||||
// Idle time represents time since "goodput".. e.g. a data or header frame
|
||||
PRIntervalTime IdleTime();
|
||||
|
||||
// Registering with a newID of 0 means pick the next available odd ID
|
||||
uint32_t RegisterStreamID(SpdyStream3 *, uint32_t aNewID = 0);
|
||||
|
||||
const static uint8_t kVersion = 3;
|
||||
|
||||
const static uint8_t kFlag_Control = 0x80;
|
||||
|
||||
const static uint8_t kFlag_Data_FIN = 0x01;
|
||||
const static uint8_t kFlag_Data_UNI = 0x02;
|
||||
|
||||
enum
|
||||
{
|
||||
CONTROL_TYPE_FIRST = 0,
|
||||
CONTROL_TYPE_SYN_STREAM = 1,
|
||||
CONTROL_TYPE_SYN_REPLY = 2,
|
||||
CONTROL_TYPE_RST_STREAM = 3,
|
||||
CONTROL_TYPE_SETTINGS = 4,
|
||||
CONTROL_TYPE_NOOP = 5, /* deprecated */
|
||||
CONTROL_TYPE_PING = 6,
|
||||
CONTROL_TYPE_GOAWAY = 7,
|
||||
CONTROL_TYPE_HEADERS = 8,
|
||||
CONTROL_TYPE_WINDOW_UPDATE = 9,
|
||||
CONTROL_TYPE_CREDENTIAL = 10,
|
||||
CONTROL_TYPE_LAST = 11
|
||||
};
|
||||
|
||||
enum rstReason
|
||||
{
|
||||
RST_PROTOCOL_ERROR = 1,
|
||||
RST_INVALID_STREAM = 2,
|
||||
RST_REFUSED_STREAM = 3,
|
||||
RST_UNSUPPORTED_VERSION = 4,
|
||||
RST_CANCEL = 5,
|
||||
RST_INTERNAL_ERROR = 6,
|
||||
RST_FLOW_CONTROL_ERROR = 7,
|
||||
RST_STREAM_IN_USE = 8,
|
||||
RST_STREAM_ALREADY_CLOSED = 9,
|
||||
RST_INVALID_CREDENTIALS = 10,
|
||||
RST_FRAME_TOO_LARGE = 11
|
||||
};
|
||||
|
||||
enum goawayReason
|
||||
{
|
||||
OK = 0,
|
||||
PROTOCOL_ERROR = 1,
|
||||
INTERNAL_ERROR = 2, // sometimes misdocumented as 11
|
||||
NUM_STATUS_CODES = 3 // reserved by chromium but undocumented
|
||||
};
|
||||
|
||||
enum settingsFlags
|
||||
{
|
||||
PERSIST_VALUE = 1,
|
||||
PERSISTED_VALUE = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SETTINGS_TYPE_UPLOAD_BW = 1, // kb/s
|
||||
SETTINGS_TYPE_DOWNLOAD_BW = 2, // kb/s
|
||||
SETTINGS_TYPE_RTT = 3, // ms
|
||||
SETTINGS_TYPE_MAX_CONCURRENT = 4, // streams
|
||||
SETTINGS_TYPE_CWND = 5, // packets
|
||||
SETTINGS_TYPE_DOWNLOAD_RETRANS_RATE = 6, // percentage
|
||||
SETTINGS_TYPE_INITIAL_WINDOW = 7, // bytes for flow control
|
||||
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
|
||||
};
|
||||
|
||||
// This should be big enough to hold all of your control packets,
|
||||
// but if it needs to grow for huge headers it can do so dynamically.
|
||||
// About 1% of responses from SPDY google services seem to be > 1000
|
||||
// with all less than 2000 when compression is enabled.
|
||||
const static uint32_t kDefaultBufferSize = 2048;
|
||||
|
||||
// kDefaultQueueSize must be >= other queue size constants
|
||||
const static uint32_t kDefaultQueueSize = 32768;
|
||||
const static uint32_t kQueueMinimumCleanup = 24576;
|
||||
const static uint32_t kQueueTailRoom = 4096;
|
||||
const static uint32_t kQueueReserved = 1024;
|
||||
|
||||
const static uint32_t kDefaultMaxConcurrent = 100;
|
||||
const static uint32_t kMaxStreamID = 0x7800000;
|
||||
|
||||
// This is a sentinel for a deleted stream. It is not a valid
|
||||
// 31 bit stream ID.
|
||||
const static uint32_t kDeadStreamID = 0xffffdead;
|
||||
|
||||
// below the emergency threshold of local window we ack every received
|
||||
// byte. Above that we coalesce bytes into the MinimumToAck size.
|
||||
const static int32_t kEmergencyWindowThreshold = 1024 * 1024;
|
||||
const static uint32_t kMinimumToAck = 64 * 1024;
|
||||
|
||||
// The default peer rwin is 64KB unless updated by a settings frame
|
||||
const static uint32_t kDefaultServerRwin = 64 * 1024;
|
||||
|
||||
static nsresult HandleSynStream(SpdySession3 *);
|
||||
static nsresult HandleSynReply(SpdySession3 *);
|
||||
static nsresult HandleRstStream(SpdySession3 *);
|
||||
static nsresult HandleSettings(SpdySession3 *);
|
||||
static nsresult HandleNoop(SpdySession3 *);
|
||||
static nsresult HandlePing(SpdySession3 *);
|
||||
static nsresult HandleGoAway(SpdySession3 *);
|
||||
static nsresult HandleHeaders(SpdySession3 *);
|
||||
static nsresult HandleWindowUpdate(SpdySession3 *);
|
||||
static nsresult HandleCredential(SpdySession3 *);
|
||||
|
||||
// For writing the SPDY data stream to LOG4
|
||||
static void LogIO(SpdySession3 *, SpdyStream3 *, const char *,
|
||||
const char *, uint32_t);
|
||||
|
||||
// an overload of nsAHttpConnection
|
||||
void TransactionHasDataToWrite(nsAHttpTransaction *);
|
||||
|
||||
// a similar version for SpdyStream3
|
||||
void TransactionHasDataToWrite(SpdyStream3 *);
|
||||
|
||||
// an overload of nsAHttpSegementReader
|
||||
virtual nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment);
|
||||
|
||||
uint32_t GetServerInitialWindow() { return mServerInitialWindow; }
|
||||
|
||||
void ConnectPushedStream(SpdyStream3 *stream);
|
||||
void DecrementConcurrent(SpdyStream3 *stream);
|
||||
|
||||
uint64_t Serial() { return mSerial; }
|
||||
|
||||
void PrintDiagnostics (nsCString &log);
|
||||
|
||||
// Streams need access to these
|
||||
uint32_t SendingChunkSize() { return mSendingChunkSize; }
|
||||
uint32_t PushAllowance() { return mPushAllowance; }
|
||||
z_stream *UpstreamZlib() { return &mUpstreamZlib; }
|
||||
nsISocketTransport *SocketTransport() { return mSocketTransport; }
|
||||
|
||||
void SendPing() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
enum stateType {
|
||||
BUFFERING_FRAME_HEADER,
|
||||
BUFFERING_CONTROL_FRAME,
|
||||
PROCESSING_DATA_FRAME,
|
||||
DISCARDING_DATA_FRAME,
|
||||
PROCESSING_COMPLETE_HEADERS,
|
||||
PROCESSING_CONTROL_RST_STREAM
|
||||
};
|
||||
|
||||
nsresult ResponseHeadersComplete();
|
||||
uint32_t GetWriteQueueSize();
|
||||
void ChangeDownstreamState(enum stateType);
|
||||
void ResetDownstreamState();
|
||||
nsresult UncompressAndDiscard(uint32_t, uint32_t);
|
||||
void zlibInit();
|
||||
void GeneratePing(uint32_t);
|
||||
void GenerateRstStream(uint32_t, uint32_t);
|
||||
void GenerateGoAway(uint32_t);
|
||||
void CleanupStream(SpdyStream3 *, nsresult, rstReason);
|
||||
void CloseStream(SpdyStream3 *, nsresult);
|
||||
void GenerateSettings();
|
||||
void RemoveStreamFromQueues(SpdyStream3 *);
|
||||
|
||||
void SetWriteCallbacks();
|
||||
void FlushOutputQueue();
|
||||
void RealignOutputQueue();
|
||||
|
||||
bool RoomForMoreConcurrent();
|
||||
void ActivateStream(SpdyStream3 *);
|
||||
void ProcessPending();
|
||||
nsresult SetInputFrameDataStream(uint32_t);
|
||||
bool VerifyStream(SpdyStream3 *, uint32_t);
|
||||
void SetNeedsCleanup();
|
||||
|
||||
void UpdateLocalRwin(SpdyStream3 *stream, uint32_t bytes);
|
||||
|
||||
// a wrapper for all calls to the nshttpconnection level segment writer. Used
|
||||
// to track network I/O for timeout purposes
|
||||
nsresult NetworkRead(nsAHttpSegmentWriter *, char *, uint32_t, uint32_t *);
|
||||
|
||||
static PLDHashOperator ShutdownEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream3> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream3> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream3> &,
|
||||
void *);
|
||||
|
||||
// This is intended to be nsHttpConnectionMgr:nsConnectionHandle taken
|
||||
// from the first transaction on this session. That object contains the
|
||||
// pointer to the real network-level nsHttpConnection object.
|
||||
nsRefPtr<nsAHttpConnection> mConnection;
|
||||
|
||||
// The underlying socket transport object is needed to propogate some events
|
||||
nsISocketTransport *mSocketTransport;
|
||||
|
||||
// These are temporary state variables to hold the argument to
|
||||
// Read/WriteSegments so it can be accessed by On(read/write)segment
|
||||
// further up the stack.
|
||||
nsAHttpSegmentReader *mSegmentReader;
|
||||
nsAHttpSegmentWriter *mSegmentWriter;
|
||||
|
||||
uint32_t mSendingChunkSize; /* the transmission chunk size */
|
||||
uint32_t mNextStreamID; /* 24 bits */
|
||||
uint32_t mConcurrentHighWater; /* max parallelism on session */
|
||||
uint32_t mPushAllowance; /* rwin for unmatched pushes */
|
||||
|
||||
stateType mDownstreamState; /* in frame, between frames, etc.. */
|
||||
|
||||
// Maintain 2 indexes - one by stream ID, one by transaction pointer.
|
||||
// There are also several lists of streams: ready to write, queued due to
|
||||
// max parallelism, streams that need to force a read for push, and the full
|
||||
// set of pushed streams.
|
||||
// The objects are not ref counted - they get destroyed
|
||||
// by the nsClassHashtable implementation when they are removed from
|
||||
// the transaction hash.
|
||||
nsDataHashtable<nsUint32HashKey, SpdyStream3 *> mStreamIDHash;
|
||||
nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
|
||||
SpdyStream3> mStreamTransactionHash;
|
||||
|
||||
nsDeque mReadyForWrite;
|
||||
nsDeque mQueuedStreams;
|
||||
nsDeque mReadyForRead;
|
||||
nsTArray<SpdyPushedStream3 *> mPushedStreams;
|
||||
|
||||
// Compression contexts for header transport using deflate.
|
||||
// SPDY compresses only HTTP headers and does not reset zlib in between
|
||||
// frames. Even data that is not associated with a stream (e.g invalid
|
||||
// stream ID) is passed through these contexts to keep the compression
|
||||
// context correct.
|
||||
z_stream mDownstreamZlib;
|
||||
z_stream mUpstreamZlib;
|
||||
|
||||
// mInputFrameBuffer is used to store received control packets and the 8 bytes
|
||||
// of header on data packets
|
||||
uint32_t mInputFrameBufferSize;
|
||||
uint32_t mInputFrameBufferUsed;
|
||||
nsAutoArrayPtr<char> mInputFrameBuffer;
|
||||
|
||||
// mInputFrameDataSize/Read are used for tracking the amount of data consumed
|
||||
// in a data frame. the data itself is not buffered in spdy
|
||||
// The frame size is mInputFrameDataSize + the constant 8 byte header
|
||||
uint32_t mInputFrameDataSize;
|
||||
uint32_t mInputFrameDataRead;
|
||||
bool mInputFrameDataLast; // This frame was marked FIN
|
||||
|
||||
// When a frame has been received that is addressed to a particular stream
|
||||
// (e.g. a data frame after the stream-id has been decoded), this points
|
||||
// to the stream.
|
||||
SpdyStream3 *mInputFrameDataStream;
|
||||
|
||||
// mNeedsCleanup is a state variable to defer cleanup of a closed stream
|
||||
// If needed, It is set in session::OnWriteSegments() and acted on and
|
||||
// cleared when the stack returns to session::WriteSegments(). The stream
|
||||
// cannot be destroyed directly out of OnWriteSegments because
|
||||
// stream::writeSegments() is on the stack at that time.
|
||||
SpdyStream3 *mNeedsCleanup;
|
||||
|
||||
// The CONTROL_TYPE value for a control frame
|
||||
uint32_t mFrameControlType;
|
||||
|
||||
// This reason code in the last processed RESET frame
|
||||
uint32_t mDownstreamRstReason;
|
||||
|
||||
// for the conversion of downstream http headers into spdy formatted headers
|
||||
// The data here does not persist between frames
|
||||
nsCString mFlatHTTPResponseHeaders;
|
||||
uint32_t mFlatHTTPResponseHeadersOut;
|
||||
|
||||
// when set, the session will go away when it reaches 0 streams. This flag
|
||||
// is set when: the stream IDs are running out (at either the client or the
|
||||
// server), when DontReuse() is called, a RST that is not specific to a
|
||||
// particular stream is received, a GOAWAY frame has been received from
|
||||
// the server.
|
||||
bool mShouldGoAway;
|
||||
|
||||
// the session has received a nsAHttpTransaction::Close() call
|
||||
bool mClosed;
|
||||
|
||||
// the session received a GoAway frame with a valid GoAwayID
|
||||
bool mCleanShutdown;
|
||||
|
||||
// indicates PROCESSING_COMPLETE_HEADERS state was pushed onto the stack
|
||||
// over an active PROCESSING_DATA_FRAME, which should be restored when
|
||||
// the processed headers are written to the stream
|
||||
bool mDataPending;
|
||||
|
||||
// If a GoAway message was received this is the ID of the last valid
|
||||
// stream. 0 otherwise. (0 is never a valid stream id.)
|
||||
uint32_t mGoAwayID;
|
||||
|
||||
// The limit on number of concurrent streams for this session. Normally it
|
||||
// is basically unlimited, but the SETTINGS control message from the
|
||||
// server might bring it down.
|
||||
uint32_t mMaxConcurrent;
|
||||
|
||||
// The actual number of concurrent streams at this moment. Generally below
|
||||
// mMaxConcurrent, but the max can be lowered in real time to a value
|
||||
// below the current value
|
||||
uint32_t mConcurrent;
|
||||
|
||||
// The number of server initiated SYN-STREAMS, tracked for telemetry
|
||||
uint32_t mServerPushedResources;
|
||||
|
||||
// The server rwin for new streams as determined from a SETTINGS frame
|
||||
uint32_t mServerInitialWindow;
|
||||
|
||||
// This is a output queue of bytes ready to be written to the SSL stream.
|
||||
// When that streams returns WOULD_BLOCK on direct write the bytes get
|
||||
// coalesced together here. This results in larger writes to the SSL layer.
|
||||
// The buffer is not dynamically grown to accomodate stream writes, but
|
||||
// does expand to accept infallible session wide frames like GoAway and RST.
|
||||
uint32_t mOutputQueueSize;
|
||||
uint32_t mOutputQueueUsed;
|
||||
uint32_t mOutputQueueSent;
|
||||
nsAutoArrayPtr<char> mOutputQueueBuffer;
|
||||
|
||||
PRIntervalTime mPingThreshold;
|
||||
PRIntervalTime mLastReadEpoch; // used for ping timeouts
|
||||
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
||||
PRIntervalTime mPingSentEpoch;
|
||||
uint32_t mNextPingID;
|
||||
|
||||
PRIntervalTime mPreviousPingThreshold; // backup for the former value
|
||||
bool mPreviousUsed; // true when backup is used
|
||||
|
||||
// used as a temporary buffer while enumerating the stream hash during GoAway
|
||||
nsDeque mGoAwayStreamsToRestart;
|
||||
|
||||
// Each session gets a unique serial number because the push cache is correlated
|
||||
// by the load group and the serial number can be used as part of the cache key
|
||||
// to make sure streams aren't shared across sessions.
|
||||
uint64_t mSerial;
|
||||
|
||||
private:
|
||||
/// connect tunnels
|
||||
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
|
||||
void RegisterTunnel(SpdyStream3 *);
|
||||
void UnRegisterTunnel(SpdyStream3 *);
|
||||
uint32_t FindTunnelCount(nsHttpConnectionInfo *);
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, uint32_t> mTunnelHash;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_SpdySession3_h
|
@ -1460,7 +1460,7 @@ SpdySession31::HandleNoop(SpdySession31 *self)
|
||||
{
|
||||
MOZ_ASSERT(self->mFrameControlType == CONTROL_TYPE_NOOP);
|
||||
|
||||
// Should not be receiving noop frames in spdy/3, so we'll just
|
||||
// Should not be receiving noop frames in spdy/3.1, so we'll just
|
||||
// make a log and ignore it
|
||||
|
||||
LOG3(("SpdySession31::HandleNoop %p NOP.", self));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,269 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_SpdyStream3_h
|
||||
#define mozilla_net_SpdyStream3_h
|
||||
|
||||
#include "nsAHttpTransaction.h"
|
||||
#include "zlib.h"
|
||||
|
||||
class nsISocketTransport;
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class SpdySession3;
|
||||
class SpdyPushedStream3;
|
||||
|
||||
class SpdyStream3 : public nsAHttpSegmentReader
|
||||
, public nsAHttpSegmentWriter
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
|
||||
SpdyStream3(nsAHttpTransaction *, SpdySession3 *, int32_t);
|
||||
|
||||
uint32_t StreamID() { return mStreamID; }
|
||||
SpdyPushedStream3 *PushSource() { return mPushSource; }
|
||||
|
||||
virtual nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *);
|
||||
virtual nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *);
|
||||
virtual bool DeferCleanupOnSuccess() { return false; }
|
||||
|
||||
const nsAFlatCString &Origin() const { return mOrigin; }
|
||||
|
||||
bool RequestBlockedOnRead()
|
||||
{
|
||||
return static_cast<bool>(mRequestBlockedOnRead);
|
||||
}
|
||||
|
||||
bool GetFullyOpen();
|
||||
// returns failure if stream cannot be made ready and stream
|
||||
// should be canceled
|
||||
nsresult SetFullyOpen();
|
||||
|
||||
bool HasRegisteredID() { return mStreamID != 0; }
|
||||
|
||||
nsAHttpTransaction *Transaction() { return mTransaction; }
|
||||
virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo()
|
||||
{
|
||||
return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr;
|
||||
}
|
||||
|
||||
void Close(nsresult reason);
|
||||
|
||||
void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; }
|
||||
bool RecvdFin() { return mRecvdFin; }
|
||||
|
||||
void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
|
||||
bool RecvdData() { return mReceivedData; }
|
||||
|
||||
void UpdateTransportSendEvents(uint32_t count);
|
||||
void UpdateTransportReadEvents(uint32_t count);
|
||||
|
||||
// The zlib header compression dictionary defined by SPDY.
|
||||
static const unsigned char kDictionary[1423];
|
||||
|
||||
nsresult Uncompress(z_stream *, char *, uint32_t);
|
||||
nsresult ConvertHeaders(nsACString &);
|
||||
|
||||
void UpdateRemoteWindow(int32_t delta);
|
||||
int64_t RemoteWindow() { return mRemoteWindow; }
|
||||
|
||||
void DecrementLocalWindow(uint32_t delta) {
|
||||
mLocalWindow -= delta;
|
||||
mLocalUnacked += delta;
|
||||
}
|
||||
|
||||
void IncrementLocalWindow(uint32_t delta) {
|
||||
mLocalWindow += delta;
|
||||
mLocalUnacked -= delta;
|
||||
}
|
||||
|
||||
uint64_t LocalUnAcked() { return mLocalUnacked; }
|
||||
int64_t LocalWindow() { return mLocalWindow; }
|
||||
|
||||
bool BlockedOnRwin() { return mBlockedOnRwin; }
|
||||
|
||||
// A pull stream has an implicit sink, a pushed stream has a sink
|
||||
// once it is matched to a pull stream.
|
||||
virtual bool HasSink() { return true; }
|
||||
|
||||
virtual ~SpdyStream3();
|
||||
|
||||
protected:
|
||||
nsresult FindHeader(nsCString, nsDependentCSubstring &);
|
||||
|
||||
static void CreatePushHashKey(const nsCString &scheme,
|
||||
const nsCString &hostHeader,
|
||||
uint64_t serial,
|
||||
const nsCSubstring &pathInfo,
|
||||
nsCString &outOrigin,
|
||||
nsCString &outKey);
|
||||
|
||||
enum stateType {
|
||||
GENERATING_SYN_STREAM,
|
||||
GENERATING_REQUEST_BODY,
|
||||
SENDING_REQUEST_BODY,
|
||||
SENDING_FIN_STREAM,
|
||||
UPSTREAM_COMPLETE
|
||||
};
|
||||
|
||||
uint32_t mStreamID;
|
||||
|
||||
// The session that this stream is a subset of
|
||||
SpdySession3 *mSession;
|
||||
|
||||
nsCString mOrigin;
|
||||
|
||||
// Each stream goes from syn_stream to upstream_complete, perhaps
|
||||
// looping on multiple instances of generating_request_body and
|
||||
// sending_request_body for each SPDY chunk in the upload.
|
||||
enum stateType mUpstreamState;
|
||||
|
||||
// Flag is set when all http request headers have been read and ID is stable
|
||||
uint32_t mSynFrameComplete : 1;
|
||||
|
||||
// Flag is set when a FIN has been placed on a data or syn packet
|
||||
// (i.e after the client has closed)
|
||||
uint32_t mSentFinOnData : 1;
|
||||
|
||||
void ChangeState(enum stateType);
|
||||
|
||||
private:
|
||||
friend class nsAutoPtr<SpdyStream3>;
|
||||
|
||||
static PLDHashOperator hdrHashEnumerate(const nsACString &,
|
||||
nsAutoPtr<nsCString> &,
|
||||
void *);
|
||||
|
||||
nsresult ParseHttpRequestHeaders(const char *, uint32_t, uint32_t *);
|
||||
void AdjustInitialWindow();
|
||||
nsresult TransmitFrame(const char *, uint32_t *, bool forceCommitment);
|
||||
void GenerateDataFrameHeader(uint32_t, bool);
|
||||
|
||||
void CompressToFrame(const nsACString &);
|
||||
void CompressToFrame(const nsACString *);
|
||||
void CompressToFrame(const char *, uint32_t);
|
||||
void CompressToFrame(uint32_t);
|
||||
void CompressFlushFrame();
|
||||
void ExecuteCompress(uint32_t);
|
||||
|
||||
// The underlying HTTP transaction. This pointer is used as the key
|
||||
// in the SpdySession3 mStreamTransactionHash so it is important to
|
||||
// keep a reference to it as long as this stream is a member of that hash.
|
||||
// (i.e. don't change it or release it after it is set in the ctor).
|
||||
nsRefPtr<nsAHttpTransaction> mTransaction;
|
||||
|
||||
// The underlying socket transport object is needed to propogate some events
|
||||
nsISocketTransport *mSocketTransport;
|
||||
|
||||
// These are temporary state variables to hold the argument to
|
||||
// Read/WriteSegments so it can be accessed by On(read/write)segment
|
||||
// further up the stack.
|
||||
nsAHttpSegmentReader *mSegmentReader;
|
||||
nsAHttpSegmentWriter *mSegmentWriter;
|
||||
|
||||
// The quanta upstream data frames are chopped into
|
||||
uint32_t mChunkSize;
|
||||
|
||||
// Flag is set when the HTTP processor has more data to send
|
||||
// but has blocked in doing so.
|
||||
uint32_t mRequestBlockedOnRead : 1;
|
||||
|
||||
// Flag is set after the response frame bearing the fin bit has
|
||||
// been processed. (i.e. after the server has closed).
|
||||
uint32_t mRecvdFin : 1;
|
||||
|
||||
// Flag is set after syn reply received
|
||||
uint32_t mFullyOpen : 1;
|
||||
|
||||
// Flag is set after the WAITING_FOR Transport event has been generated
|
||||
uint32_t mSentWaitingFor : 1;
|
||||
|
||||
// Flag is set after 1st DATA frame has been passed to stream, after
|
||||
// which additional HEADERS data is invalid
|
||||
uint32_t mReceivedData : 1;
|
||||
|
||||
// Flag is set after TCP send autotuning has been disabled
|
||||
uint32_t mSetTCPSocketBuffer : 1;
|
||||
|
||||
// The InlineFrame and associated data is used for composing control
|
||||
// frames and data frame headers.
|
||||
nsAutoArrayPtr<uint8_t> mTxInlineFrame;
|
||||
uint32_t mTxInlineFrameSize;
|
||||
uint32_t mTxInlineFrameUsed;
|
||||
|
||||
// mTxStreamFrameSize tracks the progress of
|
||||
// transmitting a request body data frame. The data frame itself
|
||||
// is never copied into the spdy layer.
|
||||
uint32_t mTxStreamFrameSize;
|
||||
|
||||
// Compression context and buffer for request header compression.
|
||||
// This is a copy of SpdySession3::mUpstreamZlib because it needs
|
||||
// to remain the same in all streams of a session.
|
||||
z_stream *mZlib;
|
||||
nsCString mFlatHttpRequestHeaders;
|
||||
|
||||
// These are used for decompressing downstream spdy response headers
|
||||
uint32_t mDecompressBufferSize;
|
||||
uint32_t mDecompressBufferUsed;
|
||||
uint32_t mDecompressedBytes;
|
||||
nsAutoArrayPtr<char> mDecompressBuffer;
|
||||
|
||||
// Track the content-length of a request body so that we can
|
||||
// place the fin flag on the last data packet instead of waiting
|
||||
// for a stream closed indication. Relying on stream close results
|
||||
// in an extra 0-length runt packet and seems to have some interop
|
||||
// problems with the google servers. Connect does rely on stream
|
||||
// close by setting this to the max value.
|
||||
int64_t mRequestBodyLenRemaining;
|
||||
|
||||
// based on nsISupportsPriority definitions
|
||||
int32_t mPriority;
|
||||
|
||||
// mLocalWindow, mRemoteWindow, and mLocalUnacked are for flow control.
|
||||
// *window are signed because they race conditions in asynchronous SETTINGS
|
||||
// messages can force them temporarily negative.
|
||||
|
||||
// LocalWindow is how much data the server will send without getting a
|
||||
// window update
|
||||
int64_t mLocalWindow;
|
||||
|
||||
// RemoteWindow is how much data the client is allowed to send without
|
||||
// getting a window update
|
||||
int64_t mRemoteWindow;
|
||||
|
||||
// LocalUnacked is the number of bytes received by the client but not
|
||||
// yet reflected in a window update. Sending that update will increment
|
||||
// LocalWindow
|
||||
uint64_t mLocalUnacked;
|
||||
|
||||
// True when sending is suspended becuase the remote flow control window is
|
||||
// <= 0
|
||||
bool mBlockedOnRwin;
|
||||
|
||||
// For Progress Events
|
||||
uint64_t mTotalSent;
|
||||
uint64_t mTotalRead;
|
||||
|
||||
// For SpdyPush
|
||||
SpdyPushedStream3 *mPushSource;
|
||||
|
||||
/// connect tunnels
|
||||
public:
|
||||
bool IsTunnel() { return mIsTunnel; }
|
||||
private:
|
||||
void ClearTransactionsBlockedOnTunnel();
|
||||
void MapStreamToPlainText();
|
||||
void MapStreamToHttpConnection();
|
||||
|
||||
bool mIsTunnel;
|
||||
bool mPlainTextTunnel;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_SpdyStream3_h
|
@ -75,11 +75,8 @@ UNIFIED_SOURCES += [
|
||||
'nsHttpResponseHead.cpp',
|
||||
'nsHttpTransaction.cpp',
|
||||
'NullHttpTransaction.cpp',
|
||||
'SpdyPush3.cpp',
|
||||
'SpdyPush31.cpp',
|
||||
'SpdySession3.cpp',
|
||||
'SpdySession31.cpp',
|
||||
'SpdyStream3.cpp',
|
||||
'SpdyStream31.cpp',
|
||||
'SpdyZlibReporter.cpp',
|
||||
'TunnelUtils.cpp',
|
||||
|
@ -27,8 +27,8 @@ class Mutex;
|
||||
|
||||
namespace net {
|
||||
enum {
|
||||
SPDY_VERSION_2_REMOVED = 2,
|
||||
SPDY_VERSION_3 = 3,
|
||||
// SPDY_VERSION_2 = 2, REMOVED
|
||||
// SPDY_VERSION_3 = 3, REMOVED
|
||||
SPDY_VERSION_31 = 4,
|
||||
HTTP_VERSION_2 = 5,
|
||||
|
||||
|
@ -179,7 +179,6 @@ nsHttpHandler::nsHttpHandler()
|
||||
, mAllowExperiments(true)
|
||||
, mHandlerActive(false)
|
||||
, mEnableSpdy(false)
|
||||
, mSpdyV3(true)
|
||||
, mSpdyV31(true)
|
||||
, mHttp2DraftEnabled(true)
|
||||
, mHttp2Enabled(true)
|
||||
@ -1177,12 +1176,6 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
mEnableSpdy = cVar;
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("spdy.enabled.v3"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.v3"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mSpdyV3 = cVar;
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("spdy.enabled.v3-1"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.v3-1"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
|
@ -96,7 +96,6 @@ public:
|
||||
bool AllowExperiments() { return mTelemetryEnabled && mAllowExperiments; }
|
||||
|
||||
bool IsSpdyEnabled() { return mEnableSpdy; }
|
||||
bool IsSpdyV3Enabled() { return mSpdyV3; }
|
||||
bool IsSpdyV31Enabled() { return mSpdyV31; }
|
||||
bool IsHttp2DraftEnabled() { return mHttp2DraftEnabled; }
|
||||
bool IsHttp2Enabled() { return mHttp2DraftEnabled && mHttp2Enabled; }
|
||||
@ -468,7 +467,6 @@ private:
|
||||
uint32_t mHandlerActive : 1;
|
||||
|
||||
uint32_t mEnableSpdy : 1;
|
||||
uint32_t mSpdyV3 : 1;
|
||||
uint32_t mSpdyV31 : 1;
|
||||
uint32_t mHttp2DraftEnabled : 1;
|
||||
uint32_t mHttp2Enabled : 1;
|
||||
|
@ -610,7 +610,7 @@ var loadGroup;
|
||||
|
||||
function resetPrefs() {
|
||||
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3", spdy3pref);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3-1", spdy3pref);
|
||||
prefs.setBoolPref("network.http.spdy.allow-push", spdypush);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2draft", http2pref);
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlspref);
|
||||
@ -634,7 +634,7 @@ function run_test() {
|
||||
|
||||
// Enable all versions of spdy to see that we auto negotiate http/2
|
||||
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
|
||||
spdy3pref = prefs.getBoolPref("network.http.spdy.enabled.v3");
|
||||
spdy3pref = prefs.getBoolPref("network.http.spdy.enabled.v3-1");
|
||||
spdypush = prefs.getBoolPref("network.http.spdy.allow-push");
|
||||
http2pref = prefs.getBoolPref("network.http.spdy.enabled.http2draft");
|
||||
tlspref = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
|
||||
@ -642,7 +642,7 @@ function run_test() {
|
||||
altsvcpref2 = prefs.getBoolPref("network.http.altsvc.oe", true);
|
||||
|
||||
prefs.setBoolPref("network.http.spdy.enabled", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3-1", true);
|
||||
prefs.setBoolPref("network.http.spdy.allow-push", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2draft", true);
|
||||
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// test spdy/3
|
||||
// test spdy/3.1
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
@ -25,7 +25,7 @@ var bigListenerMD5 = '8f607cfdd2c87d6a7eedb657dafbd836';
|
||||
|
||||
function checkIsSpdy(request) {
|
||||
try {
|
||||
if (request.getResponseHeader("X-Firefox-Spdy") == "3") {
|
||||
if (request.getResponseHeader("X-Firefox-Spdy") == "3.1") {
|
||||
if (request.getResponseHeader("X-Connection-Spdy") == "yes") {
|
||||
return true;
|
||||
}
|
||||
@ -392,7 +392,7 @@ var loadGroup;
|
||||
|
||||
function resetPrefs() {
|
||||
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3", spdy3pref);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3-1", spdy3pref);
|
||||
prefs.setBoolPref("network.http.spdy.allow-push", spdypush);
|
||||
}
|
||||
|
||||
@ -410,12 +410,12 @@ function run_test() {
|
||||
|
||||
prefs.setIntPref("network.http.speculative-parallel-limit", oldPref);
|
||||
|
||||
// Enable all versions of spdy to see that we auto negotiate spdy/3
|
||||
// Enable all versions of spdy to see that we auto negotiate spdy/3.1
|
||||
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
|
||||
spdy3pref = prefs.getBoolPref("network.http.spdy.enabled.v3");
|
||||
spdy3pref = prefs.getBoolPref("network.http.spdy.enabled.v3-1");
|
||||
spdypush = prefs.getBoolPref("network.http.spdy.allow-push");
|
||||
prefs.setBoolPref("network.http.spdy.enabled", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.v3-1", true);
|
||||
prefs.setBoolPref("network.http.spdy.allow-push", true);
|
||||
|
||||
loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
|
||||
|
Loading…
Reference in New Issue
Block a user