mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
bug 912549 - spdy/3.1 r=hurley
--HG-- rename : netwerk/protocol/http/PSpdyPush3.h => netwerk/protocol/http/PSpdyPush.h
This commit is contained in:
parent
5925bfa7a6
commit
70a6addf38
@ -1094,6 +1094,7 @@ pref("network.http.bypass-cachelock-threshold", 250);
|
||||
pref("network.http.spdy.enabled", true);
|
||||
pref("network.http.spdy.enabled.v2", true);
|
||||
pref("network.http.spdy.enabled.v3", true);
|
||||
pref("network.http.spdy.enabled.v3-1", true);
|
||||
pref("network.http.spdy.chunk-size", 4096);
|
||||
pref("network.http.spdy.timeout", 180);
|
||||
pref("network.http.spdy.coalesce-hostnames", true);
|
||||
|
@ -96,22 +96,22 @@ interface nsILoadGroup : nsIRequest
|
||||
};
|
||||
|
||||
%{C++
|
||||
// Forward-declare mozilla::net::SpdyPushCache3
|
||||
// Forward-declare mozilla::net::SpdyPushCache
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
class SpdyPushCache3;
|
||||
class SpdyPushCache;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
[ptr] native SpdyPushCache3Ptr(mozilla::net::SpdyPushCache3);
|
||||
[ptr] native SpdyPushCachePtr(mozilla::net::SpdyPushCache);
|
||||
|
||||
/**
|
||||
* Used to maintain state about the connections of a load group and
|
||||
* how they interact with blocking items like HEAD css/js loads.
|
||||
*/
|
||||
|
||||
[uuid(5361f30e-f968-437c-8f41-69d2756a6022)]
|
||||
[uuid(fdc9659c-b597-4ac0-9c9e-14b04dbb682f)]
|
||||
interface nsILoadGroupConnectionInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -137,5 +137,5 @@ interface nsILoadGroupConnectionInfo : nsISupports
|
||||
* and will destroy it when overwritten or when the load group
|
||||
* ends.
|
||||
*/
|
||||
[noscript] attribute SpdyPushCache3Ptr spdyPushCache3;
|
||||
[noscript] attribute SpdyPushCachePtr spdyPushCache;
|
||||
};
|
||||
|
@ -574,8 +574,12 @@ HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
|
||||
{
|
||||
if (pv == SPDY_VERSION_2)
|
||||
protocolVersion.Assign(NS_LITERAL_STRING("spdy/2"));
|
||||
else
|
||||
else if (pv == SPDY_VERSION_3)
|
||||
protocolVersion.Assign(NS_LITERAL_STRING("spdy/3"));
|
||||
else {
|
||||
MOZ_ASSERT (pv == SPDY_VERSION_31);
|
||||
protocolVersion.Assign(NS_LITERAL_STRING("spdy/3.1"));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/net/PSpdyPush3.h"
|
||||
#include "mozilla/net/PSpdyPush.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
@ -1101,7 +1101,7 @@ public:
|
||||
nsLoadGroupConnectionInfo();
|
||||
private:
|
||||
Atomic<uint32_t> mBlockingTransactionCount;
|
||||
nsAutoPtr<mozilla::net::SpdyPushCache3> mSpdyCache3;
|
||||
nsAutoPtr<mozilla::net::SpdyPushCache> mSpdyCache;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsLoadGroupConnectionInfo, nsILoadGroupConnectionInfo)
|
||||
@ -1135,17 +1135,18 @@ nsLoadGroupConnectionInfo::RemoveBlockingTransaction(uint32_t *_retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] attribute SpdyPushCache3Ptr spdyPushCache3; */
|
||||
/* [noscript] attribute SpdyPushCachePtr spdyPushCache; */
|
||||
NS_IMETHODIMP
|
||||
nsLoadGroupConnectionInfo::GetSpdyPushCache3(mozilla::net::SpdyPushCache3 **aSpdyPushCache3)
|
||||
nsLoadGroupConnectionInfo::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
|
||||
{
|
||||
*aSpdyPushCache3 = mSpdyCache3.get();
|
||||
*aSpdyPushCache = mSpdyCache.get();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLoadGroupConnectionInfo::SetSpdyPushCache3(mozilla::net::SpdyPushCache3 *aSpdyPushCache3)
|
||||
nsLoadGroupConnectionInfo::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
|
||||
{
|
||||
mSpdyCache3 = aSpdyPushCache3;
|
||||
mSpdyCache = aSpdyPushCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,21 @@
|
||||
// HttpLog.h should generally be included first
|
||||
#include "HttpLog.h"
|
||||
|
||||
/*
|
||||
Currently supported are spdy/3.1 and spdy/3 and spdy/2
|
||||
|
||||
*/
|
||||
|
||||
#include "nsHttp.h"
|
||||
#include "nsHttpHandler.h"
|
||||
|
||||
#include "ASpdySession.h"
|
||||
#include "PSpdyPush.h"
|
||||
#include "SpdyPush3.h"
|
||||
#include "SpdyPush31.h"
|
||||
#include "SpdySession2.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdySession31.h"
|
||||
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
@ -28,7 +37,8 @@ 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_2 ||
|
||||
version == SPDY_VERSION_3,
|
||||
version == SPDY_VERSION_3 ||
|
||||
version == SPDY_VERSION_31 ,
|
||||
"Unsupported spdy version");
|
||||
|
||||
// Don't do a runtime check of IsSpdyV?Enabled() here because pref value
|
||||
@ -38,32 +48,40 @@ ASpdySession::NewSpdySession(uint32_t version,
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SPDY_VERSION2, version);
|
||||
|
||||
if (version == SPDY_VERSION_3)
|
||||
return new SpdySession3(aTransaction, aTransport, aPriority);
|
||||
|
||||
if (version == SPDY_VERSION_2)
|
||||
return new SpdySession2(aTransaction, aTransport, aPriority);
|
||||
|
||||
return new SpdySession3(aTransaction, aTransport, aPriority);
|
||||
return new SpdySession31(aTransaction, aTransport, aPriority);
|
||||
}
|
||||
|
||||
SpdyInformation::SpdyInformation()
|
||||
{
|
||||
// list the preferred version first
|
||||
Version[0] = SPDY_VERSION_3;
|
||||
VersionString[0] = NS_LITERAL_CSTRING("spdy/3");
|
||||
Version[0] = SPDY_VERSION_2;
|
||||
VersionString[0] = NS_LITERAL_CSTRING("spdy/2");
|
||||
|
||||
Version[1] = SPDY_VERSION_2;
|
||||
VersionString[1] = NS_LITERAL_CSTRING("spdy/2");
|
||||
Version[1] = SPDY_VERSION_3;
|
||||
VersionString[1] = NS_LITERAL_CSTRING("spdy/3");
|
||||
|
||||
Version[2] = SPDY_VERSION_31;
|
||||
VersionString[2] = NS_LITERAL_CSTRING("spdy/3.1");
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyInformation::ProtocolEnabled(uint32_t index)
|
||||
{
|
||||
if (index == 0)
|
||||
return gHttpHandler->IsSpdyV3Enabled();
|
||||
MOZ_ASSERT(index < kCount, "index out of range");
|
||||
|
||||
if (index == 1)
|
||||
switch (index) {
|
||||
case 0:
|
||||
return gHttpHandler->IsSpdyV2Enabled();
|
||||
|
||||
MOZ_ASSERT(false, "index out of range");
|
||||
case 1:
|
||||
return gHttpHandler->IsSpdyV3Enabled();
|
||||
case 2:
|
||||
return gHttpHandler->IsSpdyV31Enabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -74,14 +92,74 @@ SpdyInformation::GetNPNVersionIndex(const nsACString &npnString,
|
||||
if (npnString.IsEmpty())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (npnString.Equals(VersionString[0]))
|
||||
*result = Version[0];
|
||||
else if (npnString.Equals(VersionString[1]))
|
||||
*result = Version[1];
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
for (uint32_t index = 0; index < kCount; ++index) {
|
||||
if (npnString.Equals(VersionString[index])) {
|
||||
*result = Version[index];
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPushCache
|
||||
//////////////////////////////////////////
|
||||
|
||||
SpdyPushCache::SpdyPushCache()
|
||||
{
|
||||
}
|
||||
|
||||
SpdyPushCache::~SpdyPushCache()
|
||||
{
|
||||
mHashSpdy3.Clear();
|
||||
mHashSpdy31.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushCache::RegisterPushedStreamSpdy3(nsCString key,
|
||||
SpdyPushedStream3 *stream)
|
||||
{
|
||||
LOG3(("SpdyPushCache::RegisterPushedStreamSpdy3 %s 0x%X\n",
|
||||
key.get(), stream->StreamID()));
|
||||
if(mHashSpdy3.Get(key))
|
||||
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)
|
||||
{
|
||||
LOG3(("SpdyPushCache::RegisterPushedStreamSpdy31 %s 0x%X\n",
|
||||
key.get(), stream->StreamID()));
|
||||
if(mHashSpdy31.Get(key))
|
||||
return false;
|
||||
mHashSpdy31.Put(key, stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
SpdyPushedStream31 *
|
||||
SpdyPushCache::RemovePushedStreamSpdy31(nsCString key)
|
||||
{
|
||||
SpdyPushedStream31 *rv = mHashSpdy31.Get(key);
|
||||
LOG3(("SpdyPushCache::RemovePushedStream %s 0x%X\n",
|
||||
key.get(), rv ? rv->StreamID() : 0));
|
||||
if (rv)
|
||||
mHashSpdy31.Remove(key);
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
|
@ -15,13 +15,6 @@ class nsISocketTransport;
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
// This is designed to handle up to 2 concrete protocol levels
|
||||
// simultaneously
|
||||
//
|
||||
// Currently supported are v3 (preferred), and v2
|
||||
// network.protocol.http.spdy.enabled.v2 (and v3) prefs can enable/disable
|
||||
// them.
|
||||
|
||||
class ASpdySession : public nsAHttpTransaction
|
||||
{
|
||||
public:
|
||||
@ -58,16 +51,17 @@ public:
|
||||
SpdyInformation();
|
||||
~SpdyInformation() {}
|
||||
|
||||
// determine if a version of the protocol is enabled. The primary
|
||||
// version is index 0, the secondary version is index 1.
|
||||
static const uint32_t kCount = 3;
|
||||
|
||||
// determine if a version of the protocol is enabled for index <= kCount
|
||||
bool ProtocolEnabled(uint32_t index);
|
||||
|
||||
// lookup a version enum based on an npn string. returns NS_OK if
|
||||
// string was known.
|
||||
nsresult GetNPNVersionIndex(const nsACString &npnString, uint8_t *result);
|
||||
|
||||
uint8_t Version[2];
|
||||
nsCString VersionString[2];
|
||||
uint8_t Version[kCount];
|
||||
nsCString VersionString[kCount];
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsHttpConnection.h"
|
||||
#include "SpdySession2.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdySession31.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsHttpRequestHead.h"
|
||||
@ -159,6 +160,43 @@ nsHttpConnection::PrintDiagnostics(nsCString &log)
|
||||
mSpdySession->PrintDiagnostics(log);
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession2::PrintDiagnostics(nsCString &log)
|
||||
{
|
||||
log.AppendPrintf(" ::: SPDY VERSION 2\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
|
||||
SpdySession3::PrintDiagnostics(nsCString &log)
|
||||
{
|
||||
@ -197,9 +235,9 @@ SpdySession3::PrintDiagnostics(nsCString &log)
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession2::PrintDiagnostics(nsCString &log)
|
||||
SpdySession31::PrintDiagnostics(nsCString &log)
|
||||
{
|
||||
log.AppendPrintf(" ::: SPDY VERSION 2\n");
|
||||
log.AppendPrintf(" ::: SPDY VERSION 3.1\n");
|
||||
log.AppendPrintf(" shouldgoaway = %d mClosed = %d CanReuse = %d nextID=0x%X\n",
|
||||
mShouldGoAway, mClosed, CanReuse(), mNextStreamID);
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
* 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
|
||||
// SPDY Server Push
|
||||
|
||||
/*
|
||||
A pushed stream is put into a memory buffer (The SpdyPushTransactionBuffer)
|
||||
@ -23,8 +22,8 @@
|
||||
client pull behavior.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_net_SpdyPush3_Public_h
|
||||
#define mozilla_net_SpdyPush3_Public_h
|
||||
#ifndef mozilla_net_SpdyPush_Public_h
|
||||
#define mozilla_net_SpdyPush_Public_h
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
@ -36,25 +35,35 @@ namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class SpdyPushedStream3;
|
||||
class SpdyPushedStream31;
|
||||
|
||||
// One Cache per load group
|
||||
class SpdyPushCache3
|
||||
// One cache per load group
|
||||
class SpdyPushCache
|
||||
{
|
||||
public:
|
||||
SpdyPushCache3();
|
||||
virtual ~SpdyPushCache3();
|
||||
|
||||
// The cache holds only weak pointers - no references
|
||||
bool RegisterPushedStream(nsCString key,
|
||||
SpdyPushedStream3 *stream);
|
||||
SpdyPushedStream3 *RemovePushedStream(nsCString key);
|
||||
SpdyPushedStream3 *GetPushedStream(nsCString key);
|
||||
SpdyPushCache();
|
||||
virtual ~SpdyPushCache();
|
||||
|
||||
// for spdy/3
|
||||
public:
|
||||
bool RegisterPushedStreamSpdy3(nsCString key,
|
||||
SpdyPushedStream3 *stream);
|
||||
SpdyPushedStream3 *RemovePushedStreamSpdy3(nsCString key);
|
||||
|
||||
private:
|
||||
nsDataHashtable<nsCStringHashKey, SpdyPushedStream3 *> mHash;
|
||||
nsDataHashtable<nsCStringHashKey, SpdyPushedStream3 *> mHashSpdy3;
|
||||
|
||||
// for spdy/3.1
|
||||
public:
|
||||
bool RegisterPushedStreamSpdy31(nsCString key,
|
||||
SpdyPushedStream31 *stream);
|
||||
SpdyPushedStream31 *RemovePushedStreamSpdy31(nsCString key);
|
||||
private:
|
||||
nsDataHashtable<nsCStringHashKey, SpdyPushedStream31 *> mHashSpdy31;
|
||||
};
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_SpdyPush3_Public_h
|
||||
#endif // mozilla_net_SpdyPush_Public_h
|
@ -10,7 +10,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "SpdyPush3.h"
|
||||
#include "PSpdyPush3.h"
|
||||
#include "PSpdyPush.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "nsHttpRequestHead.h"
|
||||
|
||||
@ -137,7 +137,7 @@ SpdyPushedStream3::IsOrphaned(TimeStamp now)
|
||||
|
||||
bool rv = ((now - mLastRead).ToSeconds() > 30.0);
|
||||
if (rv) {
|
||||
LOG3(("SpdyPushCache3::IsOrphaned 0x%X IsOrphaned %3.2f\n",
|
||||
LOG3(("SpdyPushCache::IsOrphaned 0x%X IsOrphaned %3.2f\n",
|
||||
mStreamID, (now - mLastRead).ToSeconds()));
|
||||
}
|
||||
return rv;
|
||||
@ -161,47 +161,6 @@ SpdyPushedStream3::GetBufferedData(char *buf,
|
||||
return rv;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPushCache3
|
||||
//////////////////////////////////////////
|
||||
|
||||
SpdyPushCache3::SpdyPushCache3()
|
||||
{
|
||||
}
|
||||
|
||||
SpdyPushCache3::~SpdyPushCache3()
|
||||
{
|
||||
}
|
||||
|
||||
SpdyPushedStream3 *
|
||||
SpdyPushCache3::GetPushedStream(nsCString key)
|
||||
{
|
||||
return mHash.Get(key);
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushCache3::RegisterPushedStream(nsCString key,
|
||||
SpdyPushedStream3 *stream)
|
||||
{
|
||||
LOG3(("SpdyPushCache3::RegisterPushedStream %s 0x%X\n",
|
||||
key.get(), stream->StreamID()));
|
||||
if(mHash.Get(key))
|
||||
return false;
|
||||
mHash.Put(key, stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
SpdyPushedStream3 *
|
||||
SpdyPushCache3::RemovePushedStream(nsCString key)
|
||||
{
|
||||
SpdyPushedStream3 *rv = mHash.Get(key);
|
||||
LOG3(("SpdyPushCache3::RemovePushedStream %s 0x%X\n",
|
||||
key.get(), rv ? rv->StreamID() : 0));
|
||||
if (rv)
|
||||
mHash.Remove(key);
|
||||
return rv;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPush3TransactionBuffer
|
||||
// This is the nsAHttpTransction owned by the stream when the pushed
|
||||
|
355
netwerk/protocol/http/SpdyPush31.cpp
Normal file
355
netwerk/protocol/http/SpdyPush31.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
/* -*- 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"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "nsDependentString.h"
|
||||
#include "SpdyPush31.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPushedStream31
|
||||
//////////////////////////////////////////
|
||||
|
||||
SpdyPushedStream31::SpdyPushedStream31(SpdyPush31TransactionBuffer *aTransaction,
|
||||
SpdySession31 *aSession,
|
||||
SpdyStream31 *aAssociatedStream,
|
||||
uint32_t aID)
|
||||
:SpdyStream31(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(("SpdyPushedStream31 ctor this=%p id=0x%X\n", this, aID));
|
||||
mStreamID = aID;
|
||||
mBufferedPush->SetPushStream(this);
|
||||
mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
|
||||
mLastRead = TimeStamp::Now();
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream31::GetPushComplete()
|
||||
{
|
||||
return mPushCompleted;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPushedStream31::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
uint32_t count,
|
||||
uint32_t *countWritten)
|
||||
{
|
||||
nsresult rv = SpdyStream31::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
|
||||
SpdyPushedStream31::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 = SpdyStream31::FindHeader(NS_LITERAL_CSTRING(":host"), host);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream31::ReadSegments session=%p ID 0x%X "
|
||||
"push without required :host\n", mSession, mStreamID));
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = SpdyStream31::FindHeader(NS_LITERAL_CSTRING(":scheme"), scheme);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream31::ReadSegments session=%p ID 0x%X "
|
||||
"push without required :scheme\n", mSession, mStreamID));
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = SpdyStream31::FindHeader(NS_LITERAL_CSTRING(":path"), path);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdyPushedStream31::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(("SpdyPushStream31 0x%X hash key %s\n", mStreamID, mHashKey.get()));
|
||||
|
||||
// the write side of a pushed transaction just involves manipulating a little state
|
||||
SpdyStream31::mSentFinOnData = 1;
|
||||
SpdyStream31::mSynFrameComplete = 1;
|
||||
SpdyStream31::ChangeState(UPSTREAM_COMPLETE);
|
||||
*count = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream31::GetHashKey(nsCString &key)
|
||||
{
|
||||
if (mHashKey.IsEmpty())
|
||||
return false;
|
||||
|
||||
key = mHashKey;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPushedStream31::ConnectPushedStream(SpdyStream31 *stream)
|
||||
{
|
||||
mSession->ConnectPushedStream(stream);
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPushedStream31::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(("SpdyPushedStream31::IsOrphaned 0x%X IsOrphaned %3.2f\n",
|
||||
mStreamID, (now - mLastRead).ToSeconds()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPushedStream31::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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// SpdyPush31TransactionBuffer
|
||||
// This is the nsAHttpTransction owned by the stream when the pushed
|
||||
// stream has not yet been matched with a pull request
|
||||
//////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS0(SpdyPush31TransactionBuffer)
|
||||
|
||||
SpdyPush31TransactionBuffer::SpdyPush31TransactionBuffer()
|
||||
: mStatus(NS_OK)
|
||||
, mRequestHead(nullptr)
|
||||
, mPushStream(nullptr)
|
||||
, mIsDone(false)
|
||||
, mBufferedHTTP1Size(kDefaultBufferSize)
|
||||
, mBufferedHTTP1Used(0)
|
||||
, mBufferedHTTP1Consumed(0)
|
||||
{
|
||||
mBufferedHTTP1 = new char[mBufferedHTTP1Size];
|
||||
}
|
||||
|
||||
SpdyPush31TransactionBuffer::~SpdyPush31TransactionBuffer()
|
||||
{
|
||||
delete mRequestHead;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush31TransactionBuffer::SetConnection(nsAHttpConnection *conn)
|
||||
{
|
||||
}
|
||||
|
||||
nsAHttpConnection *
|
||||
SpdyPush31TransactionBuffer::Connection()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush31TransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
|
||||
{
|
||||
*outCB = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush31TransactionBuffer::OnTransportStatus(nsITransport* transport,
|
||||
nsresult status, uint64_t progress)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyPush31TransactionBuffer::IsDone()
|
||||
{
|
||||
return mIsDone;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::Status()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush31TransactionBuffer::Caps()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
SpdyPush31TransactionBuffer::Available()
|
||||
{
|
||||
return mBufferedHTTP1Used - mBufferedHTTP1Consumed;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::ReadSegments(nsAHttpSegmentReader *reader,
|
||||
uint32_t count, uint32_t *countRead)
|
||||
{
|
||||
*countRead = 0;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
uint32_t count, uint32_t *countWritten)
|
||||
{
|
||||
if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
|
||||
SpdySession31::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()) {
|
||||
SpdyStream31 *consumer = mPushStream->GetConsumerStream();
|
||||
|
||||
if (consumer) {
|
||||
LOG3(("SpdyPush31TransactionBuffer::WriteSegments notifying connection "
|
||||
"consumer data available 0x%X [%u]\n",
|
||||
mPushStream->StreamID(), Available()));
|
||||
mPushStream->ConnectPushedStream(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush31TransactionBuffer::Http1xTransactionCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsHttpRequestHead *
|
||||
SpdyPush31TransactionBuffer::RequestHead()
|
||||
{
|
||||
if (!mRequestHead)
|
||||
mRequestHead = new nsHttpRequestHead();
|
||||
return mRequestHead;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush31TransactionBuffer::SetProxyConnectFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpdyPush31TransactionBuffer::Close(nsresult reason)
|
||||
{
|
||||
mStatus = reason;
|
||||
mIsDone = true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::AddTransaction(nsAHttpTransaction *trans)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SpdyPush31TransactionBuffer::PipelineDepth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::SetPipelinePosition(int32_t position)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t
|
||||
SpdyPush31TransactionBuffer::PipelinePosition()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyPush31TransactionBuffer::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
|
101
netwerk/protocol/http/SpdyPush31.h
Normal file
101
netwerk/protocol/http/SpdyPush31.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* -*- 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/3.1
|
||||
|
||||
#ifndef mozilla_net_SpdyPush31_Internal_h
|
||||
#define mozilla_net_SpdyPush3_Internal_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsHttpRequestHead.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsString.h"
|
||||
#include "PSpdyPush.h"
|
||||
#include "SpdySession31.h"
|
||||
#include "SpdyStream31.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class SpdyPush31TransactionBuffer;
|
||||
|
||||
class SpdyPushedStream31 MOZ_FINAL : public SpdyStream31
|
||||
{
|
||||
public:
|
||||
SpdyPushedStream31(SpdyPush31TransactionBuffer *aTransaction,
|
||||
SpdySession31 *aSession,
|
||||
SpdyStream31 *aAssociatedStream,
|
||||
uint32_t aID);
|
||||
virtual ~SpdyPushedStream31() {}
|
||||
|
||||
bool GetPushComplete();
|
||||
SpdyStream31 *GetConsumerStream() { return mConsumerStream; };
|
||||
void SetConsumerStream(SpdyStream31 *aStream) { mConsumerStream = aStream; }
|
||||
bool GetHashKey(nsCString &key);
|
||||
|
||||
// override of SpdyStream31
|
||||
nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *);
|
||||
nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *);
|
||||
|
||||
nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() { return mLoadGroupCI; };
|
||||
void ConnectPushedStream(SpdyStream31 *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 SpdyStream31
|
||||
virtual bool HasSink() { return !!mConsumerStream; }
|
||||
|
||||
private:
|
||||
|
||||
SpdyStream31 *mConsumerStream; // paired request stream that consumes from
|
||||
// real spdy one.. null until a match is made.
|
||||
|
||||
nsCOMPtr<nsILoadGroupConnectionInfo> mLoadGroupCI;
|
||||
|
||||
SpdyPush31TransactionBuffer *mBufferedPush;
|
||||
mozilla::TimeStamp mLastRead;
|
||||
|
||||
nsCString mHashKey;
|
||||
nsresult mStatus;
|
||||
bool mPushCompleted; // server push FIN received
|
||||
bool mDeferCleanupOnSuccess;
|
||||
};
|
||||
|
||||
class SpdyPush31TransactionBuffer MOZ_FINAL : public nsAHttpTransaction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
|
||||
SpdyPush31TransactionBuffer();
|
||||
virtual ~SpdyPush31TransactionBuffer();
|
||||
|
||||
nsresult GetBufferedData(char *buf, uint32_t count, uint32_t *countWritten);
|
||||
void SetPushStream(SpdyPushedStream31 *stream) { mPushStream = stream; }
|
||||
|
||||
private:
|
||||
const static uint32_t kDefaultBufferSize = 4096;
|
||||
|
||||
nsresult mStatus;
|
||||
nsHttpRequestHead *mRequestHead;
|
||||
SpdyPushedStream31 *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
|
@ -16,7 +16,7 @@
|
||||
#include "SpdyPush3.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdyStream3.h"
|
||||
#include "PSpdyPush3.h"
|
||||
#include "PSpdyPush.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -988,7 +988,7 @@ SpdySession3::HandleSynStream(SpdySession3 *self)
|
||||
self->mShouldGoAway = true;
|
||||
|
||||
bool resetStream = true;
|
||||
SpdyPushCache3 *cache = nullptr;
|
||||
SpdyPushCache *cache = nullptr;
|
||||
|
||||
if (!(flags & kFlag_Data_UNI)) {
|
||||
// pushed streams require UNIDIRECTIONAL flag
|
||||
@ -1017,10 +1017,10 @@ SpdySession3::HandleSynStream(SpdySession3 *self)
|
||||
} else {
|
||||
nsILoadGroupConnectionInfo *loadGroupCI = associatedStream->LoadGroupConnectionInfo();
|
||||
if (loadGroupCI) {
|
||||
loadGroupCI->GetSpdyPushCache3(&cache);
|
||||
loadGroupCI->GetSpdyPushCache(&cache);
|
||||
if (!cache) {
|
||||
cache = new SpdyPushCache3();
|
||||
if (!cache || NS_FAILED(loadGroupCI->SetSpdyPushCache3(cache))) {
|
||||
cache = new SpdyPushCache();
|
||||
if (!cache || NS_FAILED(loadGroupCI->SetSpdyPushCache(cache))) {
|
||||
delete cache;
|
||||
cache = nullptr;
|
||||
}
|
||||
@ -1101,7 +1101,7 @@ SpdySession3::HandleSynStream(SpdySession3 *self)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!cache->RegisterPushedStream(key, pushedStream)) {
|
||||
if (!cache->RegisterPushedStreamSpdy3(key, pushedStream)) {
|
||||
LOG(("SpdySession3::HandleSynStream registerPushedStream Failed\n"));
|
||||
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, RST_INVALID_STREAM);
|
||||
self->ResetDownstreamState();
|
||||
|
2857
netwerk/protocol/http/SpdySession31.cpp
Normal file
2857
netwerk/protocol/http/SpdySession31.cpp
Normal file
File diff suppressed because it is too large
Load Diff
407
netwerk/protocol/http/SpdySession31.h
Normal file
407
netwerk/protocol/http/SpdySession31.h
Normal file
@ -0,0 +1,407 @@
|
||||
/* -*- 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_SpdySession31_h
|
||||
#define mozilla_net_SpdySession31_h
|
||||
|
||||
// spdy/3.1
|
||||
|
||||
#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 SpdyPushedStream31;
|
||||
class SpdyStream31;
|
||||
|
||||
class SpdySession31 MOZ_FINAL : public ASpdySession
|
||||
, public nsAHttpConnection
|
||||
, public nsAHttpSegmentReader
|
||||
, public nsAHttpSegmentWriter
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
NS_DECL_NSAHTTPCONNECTION(mConnection)
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
|
||||
SpdySession31(nsAHttpTransaction *, nsISocketTransport *, int32_t);
|
||||
~SpdySession31();
|
||||
|
||||
bool AddStream(nsAHttpTransaction *, int32_t);
|
||||
bool CanReuse() { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams();
|
||||
|
||||
// When the connection is active this is called every 1 second
|
||||
void 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(SpdyStream31 *, 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 rwin is 64KB unless updated by a settings frame
|
||||
const static uint32_t kDefaultRwin = 64 * 1024;
|
||||
|
||||
static nsresult HandleSynStream(SpdySession31 *);
|
||||
static nsresult HandleSynReply(SpdySession31 *);
|
||||
static nsresult HandleRstStream(SpdySession31 *);
|
||||
static nsresult HandleSettings(SpdySession31 *);
|
||||
static nsresult HandleNoop(SpdySession31 *);
|
||||
static nsresult HandlePing(SpdySession31 *);
|
||||
static nsresult HandleGoAway(SpdySession31 *);
|
||||
static nsresult HandleHeaders(SpdySession31 *);
|
||||
static nsresult HandleWindowUpdate(SpdySession31 *);
|
||||
static nsresult HandleCredential(SpdySession31 *);
|
||||
|
||||
template<typename T>
|
||||
static void EnsureBuffer(nsAutoArrayPtr<T> &,
|
||||
uint32_t, uint32_t, uint32_t &);
|
||||
|
||||
// For writing the SPDY data stream to LOG4
|
||||
static void LogIO(SpdySession31 *, SpdyStream31 *, const char *,
|
||||
const char *, uint32_t);
|
||||
|
||||
// an overload of nsAHttpConnection
|
||||
void TransactionHasDataToWrite(nsAHttpTransaction *);
|
||||
|
||||
// a similar version for SpdyStream31
|
||||
void TransactionHasDataToWrite(SpdyStream31 *);
|
||||
|
||||
// an overload of nsAHttpSegementReader
|
||||
virtual nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment);
|
||||
|
||||
uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; }
|
||||
|
||||
void ConnectPushedStream(SpdyStream31 *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; }
|
||||
int64_t RemoteSessionWindow() { return mRemoteSessionWindow; }
|
||||
void DecrementRemoteSessionWindow (uint32_t bytes) { mRemoteSessionWindow -= bytes; }
|
||||
|
||||
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 DecrementConcurrent(SpdyStream31 *);
|
||||
void zlibInit();
|
||||
void GeneratePing(uint32_t);
|
||||
void GenerateRstStream(uint32_t, uint32_t);
|
||||
void GenerateGoAway(uint32_t);
|
||||
void CleanupStream(SpdyStream31 *, nsresult, rstReason);
|
||||
void CloseStream(SpdyStream31 *, nsresult);
|
||||
void GenerateSettings();
|
||||
void RemoveStreamFromQueues(SpdyStream31 *);
|
||||
|
||||
void SetWriteCallbacks();
|
||||
void FlushOutputQueue();
|
||||
void RealignOutputQueue();
|
||||
|
||||
bool RoomForMoreConcurrent();
|
||||
void ActivateStream(SpdyStream31 *);
|
||||
void ProcessPending();
|
||||
nsresult SetInputFrameDataStream(uint32_t);
|
||||
bool VerifyStream(SpdyStream31 *, uint32_t);
|
||||
void SetNeedsCleanup();
|
||||
|
||||
void UpdateLocalRwin(SpdyStream31 *stream, uint32_t bytes);
|
||||
void UpdateLocalStreamWindow(SpdyStream31 *stream, uint32_t bytes);
|
||||
void UpdateLocalSessionWindow(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<SpdyStream31> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream31> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream31> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator RestartBlockedOnRwinEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream31> &,
|
||||
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, SpdyStream31 *> mStreamIDHash;
|
||||
nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
|
||||
SpdyStream31> mStreamTransactionHash;
|
||||
|
||||
nsDeque mReadyForWrite;
|
||||
nsDeque mQueuedStreams;
|
||||
nsDeque mReadyForRead;
|
||||
nsTArray<SpdyPushedStream31 *> 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.
|
||||
SpdyStream31 *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.
|
||||
SpdyStream31 *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 mServerInitialStreamWindow;
|
||||
|
||||
// The Local Session window is how much data the server is allowed to send
|
||||
// (across all streams) without getting a window update to stream 0. It is
|
||||
// signed because asynchronous changes via SETTINGS can drive it negative.
|
||||
int64_t mLocalSessionWindow;
|
||||
|
||||
// The Remote Session Window is how much data the client is allowed to send
|
||||
// (across all streams) without receiving a window update to stream 0. It is
|
||||
// signed because asynchronous changes via SETTINGS can drive it negative.
|
||||
int64_t mRemoteSessionWindow;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_SpdySession31_h
|
@ -17,7 +17,7 @@
|
||||
#include "SpdyPush3.h"
|
||||
#include "SpdySession3.h"
|
||||
#include "SpdyStream3.h"
|
||||
#include "PSpdyPush3.h"
|
||||
#include "PSpdyPush.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -285,16 +285,16 @@ SpdyStream3::ParseHttpRequestHeaders(const char *buf,
|
||||
if (mTransaction->RequestHead()->Method() == nsHttp::Get) {
|
||||
// from :scheme, :host, :path
|
||||
nsILoadGroupConnectionInfo *loadGroupCI = mTransaction->LoadGroupConnectionInfo();
|
||||
SpdyPushCache3 *cache = nullptr;
|
||||
SpdyPushCache *cache = nullptr;
|
||||
if (loadGroupCI)
|
||||
loadGroupCI->GetSpdyPushCache3(&cache);
|
||||
loadGroupCI->GetSpdyPushCache(&cache);
|
||||
|
||||
SpdyPushedStream3 *pushedStream = nullptr;
|
||||
// we remove the pushedstream from the push cache so that
|
||||
// it will not be used for another GET. This does not destroy the
|
||||
// stream itself - that is done when the transactionhash is done with it.
|
||||
if (cache)
|
||||
pushedStream = cache->RemovePushedStream(hashkey);
|
||||
pushedStream = cache->RemovePushedStreamSpdy3(hashkey);
|
||||
|
||||
if (pushedStream) {
|
||||
LOG3(("Pushed Stream Match located id=0x%X key=%s\n",
|
||||
|
1474
netwerk/protocol/http/SpdyStream31.cpp
Normal file
1474
netwerk/protocol/http/SpdyStream31.cpp
Normal file
File diff suppressed because it is too large
Load Diff
258
netwerk/protocol/http/SpdyStream31.h
Normal file
258
netwerk/protocol/http/SpdyStream31.h
Normal file
@ -0,0 +1,258 @@
|
||||
/* -*- 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_SpdyStream31_h
|
||||
#define mozilla_net_SpdyStream31_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAHttpTransaction.h"
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class SpdyStream31 : public nsAHttpSegmentReader
|
||||
, public nsAHttpSegmentWriter
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
|
||||
SpdyStream31(nsAHttpTransaction *, SpdySession31 *, int32_t);
|
||||
|
||||
uint32_t StreamID() { return mStreamID; }
|
||||
SpdyPushedStream31 *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);
|
||||
}
|
||||
|
||||
// returns false if called more than once
|
||||
bool GetFullyOpen() {return mFullyOpen;}
|
||||
void SetFullyOpen()
|
||||
{
|
||||
MOZ_ASSERT(!mFullyOpen);
|
||||
mFullyOpen = 1;
|
||||
}
|
||||
|
||||
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,
|
||||
// and hooks to the mozilla allocator for zlib to use.
|
||||
static const unsigned char kDictionary[1423];
|
||||
static void *zlib_allocator(void *, uInt, uInt);
|
||||
static void zlib_destructor(void *, void *);
|
||||
|
||||
nsresult Uncompress(z_stream *, char *, uint32_t);
|
||||
nsresult ConvertHeaders(nsACString &);
|
||||
|
||||
void UpdateRemoteWindow(int32_t delta) { mRemoteWindow += 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 ~SpdyStream31();
|
||||
|
||||
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
|
||||
SpdySession31 *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<SpdyStream31>;
|
||||
|
||||
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 SpdySession31 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 SpdySession31::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.
|
||||
int64_t mRequestBodyLenRemaining;
|
||||
|
||||
// based on nsISupportsPriority definitions
|
||||
int32_t mPriority;
|
||||
|
||||
// mLocalWindow, mRemoteWindow, and mLocalUnacked are for flow control.
|
||||
// *window are signed because the 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
|
||||
SpdyPushedStream31 *mPushSource;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_SpdyStream31_h
|
@ -36,7 +36,7 @@ EXPORTS.mozilla.net += [
|
||||
'HttpChannelParent.h',
|
||||
'HttpInfo.h',
|
||||
'PHttpChannelParams.h',
|
||||
'PSpdyPush3.h',
|
||||
'PSpdyPush.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
@ -49,10 +49,13 @@ CPP_SOURCES += [
|
||||
'HttpInfo.cpp',
|
||||
'NullHttpTransaction.cpp',
|
||||
'SpdyPush3.cpp',
|
||||
'SpdyPush31.cpp',
|
||||
'SpdySession2.cpp',
|
||||
'SpdySession3.cpp',
|
||||
'SpdySession31.cpp',
|
||||
'SpdyStream2.cpp',
|
||||
'SpdyStream3.cpp',
|
||||
'SpdyStream31.cpp',
|
||||
'nsHttp.cpp',
|
||||
'nsHttpActivityDistributor.cpp',
|
||||
'nsHttpAuthCache.cpp',
|
||||
|
@ -25,7 +25,8 @@ class Mutex;
|
||||
namespace net {
|
||||
enum {
|
||||
SPDY_VERSION_2 = 2,
|
||||
SPDY_VERSION_3 = 3
|
||||
SPDY_VERSION_3 = 3,
|
||||
SPDY_VERSION_31 = 4
|
||||
};
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
@ -272,7 +272,7 @@ nsHttpConnection::EnsureNPNComplete()
|
||||
if (NS_FAILED(rv))
|
||||
goto npnComplete;
|
||||
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p negotiated to '%s'",
|
||||
LOG(("nsHttpConnection::EnsureNPNComplete %p negotiated to '%s'\n",
|
||||
this, negotiatedNPN.get()));
|
||||
|
||||
uint8_t spdyVersion;
|
||||
@ -408,12 +408,11 @@ nsHttpConnection::SetupSSL(uint32_t caps)
|
||||
if (gHttpHandler->IsSpdyEnabled() &&
|
||||
!(caps & NS_HTTP_DISALLOW_SPDY)) {
|
||||
LOG(("nsHttpConnection::SetupSSL Allow SPDY NPN selection"));
|
||||
if (gHttpHandler->SpdyInfo()->ProtocolEnabled(0))
|
||||
protocolArray.AppendElement(
|
||||
gHttpHandler->SpdyInfo()->VersionString[0]);
|
||||
if (gHttpHandler->SpdyInfo()->ProtocolEnabled(1))
|
||||
protocolArray.AppendElement(
|
||||
gHttpHandler->SpdyInfo()->VersionString[1]);
|
||||
for (uint32_t index = 0; index < SpdyInformation::kCount; ++index) {
|
||||
if (gHttpHandler->SpdyInfo()->ProtocolEnabled(index))
|
||||
protocolArray.AppendElement(
|
||||
gHttpHandler->SpdyInfo()->VersionString[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(ssl->SetNPNList(protocolArray))) {
|
||||
|
@ -186,6 +186,7 @@ nsHttpHandler::nsHttpHandler()
|
||||
, mEnableSpdy(false)
|
||||
, mSpdyV2(true)
|
||||
, mSpdyV3(true)
|
||||
, mSpdyV31(true)
|
||||
, mCoalesceSpdy(true)
|
||||
, mSpdyPersistentSettings(false)
|
||||
, mAllowSpdyPush(true)
|
||||
@ -1136,6 +1137,12 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
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))
|
||||
mSpdyV31 = cVar;
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
|
@ -97,6 +97,7 @@ public:
|
||||
bool IsSpdyEnabled() { return mEnableSpdy; }
|
||||
bool IsSpdyV2Enabled() { return mSpdyV2; }
|
||||
bool IsSpdyV3Enabled() { return mSpdyV3; }
|
||||
bool IsSpdyV31Enabled() { return mSpdyV31; }
|
||||
bool CoalesceSpdy() { return mCoalesceSpdy; }
|
||||
bool UseSpdyPersistentSettings() { return mSpdyPersistentSettings; }
|
||||
uint32_t SpdySendingChunkSize() { return mSpdySendingChunkSize; }
|
||||
@ -417,6 +418,7 @@ private:
|
||||
bool mEnableSpdy;
|
||||
bool mSpdyV2;
|
||||
bool mSpdyV3;
|
||||
bool mSpdyV31;
|
||||
bool mCoalesceSpdy;
|
||||
bool mSpdyPersistentSettings;
|
||||
bool mAllowSpdyPush;
|
||||
|
Loading…
Reference in New Issue
Block a user