зеркало из https://github.com/mozilla/gecko-dev.git
bug 737470 patch 3 implement spdy v3 (pref off) r=honzab
This commit is contained in:
Родитель
e68b6e9d07
Коммит
cae1bafa38
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -41,7 +41,7 @@
|
|||
#define mozilla_net_SpdySession3_h
|
||||
|
||||
// SPDY as defined by
|
||||
// http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2
|
||||
// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
|
||||
|
||||
#include "ASpdySession.h"
|
||||
#include "nsClassHashtable.h"
|
||||
|
@ -84,26 +84,13 @@ public:
|
|||
|
||||
PRUint32 RegisterStreamID(SpdyStream3 *);
|
||||
|
||||
const static PRUint8 kVersion = 3;
|
||||
|
||||
const static PRUint8 kFlag_Control = 0x80;
|
||||
|
||||
const static PRUint8 kFlag_Data_FIN = 0x01;
|
||||
const static PRUint8 kFlag_Data_UNI = 0x02;
|
||||
const static PRUint8 kFlag_Data_ZLIB = 0x02;
|
||||
|
||||
// The protocol document for v2 specifies that the
|
||||
// highest value (3) is the highest priority, but in
|
||||
// reality 0 is the highest priority.
|
||||
//
|
||||
// Draft 3 notes here https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/
|
||||
// are the best guide to the mistake. Also see
|
||||
// GetLowestPriority() and GetHighestPriority() in spdy_framer.h of
|
||||
// chromium source.
|
||||
|
||||
const static PRUint8 kPri00 = 0 << 6; // highest
|
||||
const static PRUint8 kPri01 = 1 << 6;
|
||||
const static PRUint8 kPri02 = 2 << 6;
|
||||
const static PRUint8 kPri03 = 3 << 6; // lowest
|
||||
|
||||
enum
|
||||
{
|
||||
CONTROL_TYPE_FIRST = 0,
|
||||
|
@ -111,12 +98,13 @@ public:
|
|||
CONTROL_TYPE_SYN_REPLY = 2,
|
||||
CONTROL_TYPE_RST_STREAM = 3,
|
||||
CONTROL_TYPE_SETTINGS = 4,
|
||||
CONTROL_TYPE_NOOP = 5,
|
||||
CONTROL_TYPE_NOOP = 5, /* deprecated */
|
||||
CONTROL_TYPE_PING = 6,
|
||||
CONTROL_TYPE_GOAWAY = 7,
|
||||
CONTROL_TYPE_HEADERS = 8,
|
||||
CONTROL_TYPE_WINDOW_UPDATE = 9, /* no longer in v2 */
|
||||
CONTROL_TYPE_LAST = 10
|
||||
CONTROL_TYPE_WINDOW_UPDATE = 9,
|
||||
CONTROL_TYPE_CREDENTIAL = 10,
|
||||
CONTROL_TYPE_LAST = 11
|
||||
};
|
||||
|
||||
enum rstReason
|
||||
|
@ -128,7 +116,10 @@ public:
|
|||
RST_CANCEL = 5,
|
||||
RST_INTERNAL_ERROR = 6,
|
||||
RST_FLOW_CONTROL_ERROR = 7,
|
||||
RST_BAD_ASSOC_STREAM = 8
|
||||
RST_STREAM_IN_USE = 8,
|
||||
RST_STREAM_ALREADY_CLOSED = 9,
|
||||
RST_INVALID_CREDENTIALS = 10,
|
||||
RST_FRAME_TOO_LARGE = 11
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -139,7 +130,8 @@ public:
|
|||
SETTINGS_TYPE_MAX_CONCURRENT = 4, // streams
|
||||
SETTINGS_TYPE_CWND = 5, // packets
|
||||
SETTINGS_TYPE_DOWNLOAD_RETRANS_RATE = 6, // percentage
|
||||
SETTINGS_TYPE_INITIAL_WINDOW = 7 // bytes. Not used in v2.
|
||||
SETTINGS_TYPE_INITIAL_WINDOW = 7, // bytes
|
||||
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
|
||||
};
|
||||
|
||||
// This should be big enough to hold all of your control packets,
|
||||
|
@ -161,6 +153,16 @@ public:
|
|||
// 31 bit stream ID.
|
||||
const static PRUint32 kDeadStreamID = 0xffffdead;
|
||||
|
||||
// until we have an API that can push back on receiving data (right now
|
||||
// WriteSegments is obligated to accept data and buffer) there is no
|
||||
// reason to throttle with the rwin other than in server push
|
||||
// scenarios.
|
||||
const static PRUint32 kInitialRwin = 256 * 1024 * 1024;
|
||||
const static PRUint32 kMinimumToAck = 64 * 1024;
|
||||
|
||||
// The default peer rwin is 64KB unless updated by a settings frame
|
||||
const static PRUint32 kDefaultServerRwin = 64 * 1024;
|
||||
|
||||
static nsresult HandleSynStream(SpdySession3 *);
|
||||
static nsresult HandleSynReply(SpdySession3 *);
|
||||
static nsresult HandleRstStream(SpdySession3 *);
|
||||
|
@ -187,6 +189,8 @@ public:
|
|||
// an overload of nsAHttpSegementReader
|
||||
virtual nsresult CommitToSegmentSize(PRUint32 size);
|
||||
|
||||
PRUint32 GetServerInitialWindow() { return mServerInitialWindow; }
|
||||
|
||||
private:
|
||||
|
||||
enum stateType {
|
||||
|
@ -194,25 +198,23 @@ private:
|
|||
BUFFERING_CONTROL_FRAME,
|
||||
PROCESSING_DATA_FRAME,
|
||||
DISCARDING_DATA_FRAME,
|
||||
PROCESSING_CONTROL_SYN_REPLY,
|
||||
PROCESSING_COMPLETE_HEADERS,
|
||||
PROCESSING_CONTROL_RST_STREAM
|
||||
};
|
||||
|
||||
void DeterminePingThreshold();
|
||||
nsresult HandleSynReplyForValidStream();
|
||||
nsresult ResponseHeadersComplete();
|
||||
PRUint32 GetWriteQueueSize();
|
||||
void ChangeDownstreamState(enum stateType);
|
||||
void ResetDownstreamState();
|
||||
nsresult DownstreamUncompress(char *, PRUint32);
|
||||
nsresult UncompressAndDiscard(PRUint32, PRUint32);
|
||||
void zlibInit();
|
||||
nsresult FindHeader(nsCString, nsDependentCSubstring &);
|
||||
nsresult ConvertHeaders(nsDependentCSubstring &,
|
||||
nsDependentCSubstring &);
|
||||
void GeneratePing(PRUint32);
|
||||
void ClearPing(bool);
|
||||
void GenerateRstStream(PRUint32, PRUint32);
|
||||
void GenerateGoAway();
|
||||
void CleanupStream(SpdyStream3 *, nsresult, rstReason);
|
||||
void GenerateSettings();
|
||||
|
||||
void SetWriteCallbacks();
|
||||
void FlushOutputQueue();
|
||||
|
@ -224,6 +226,8 @@ private:
|
|||
bool VerifyStream(SpdyStream3 *, PRUint32);
|
||||
void SetNeedsCleanup();
|
||||
|
||||
void UpdateLocalRwin(SpdyStream3 *stream, PRUint32 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 *, PRUint32, PRUint32 *);
|
||||
|
@ -232,6 +236,10 @@ private:
|
|||
nsAutoPtr<SpdyStream3> &,
|
||||
void *);
|
||||
|
||||
static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
|
||||
nsAutoPtr<SpdyStream3> &,
|
||||
void *);
|
||||
|
||||
// This is intended to be nsHttpConnectionMgr:nsHttpConnectionHandle taken
|
||||
// from the first transaction on this session. That object contains the
|
||||
// pointer to the real network-level nsHttpConnection object.
|
||||
|
@ -252,28 +260,23 @@ private:
|
|||
|
||||
stateType mDownstreamState; /* in frame, between frames, etc.. */
|
||||
|
||||
// Maintain 5 indexes - one by stream ID, one by transaction ptr,
|
||||
// Maintain 4 indexes - one by stream ID, one by transaction ptr,
|
||||
// one list of streams ready to write, one list of streams that are queued
|
||||
// due to max parallelism settings, and one list of streams
|
||||
// that must be given priority to write for window updates. The objects
|
||||
// due to max parallelism settings. The objects
|
||||
// are not ref counted - they get destroyed
|
||||
// by the nsClassHashtable implementation when they are removed from
|
||||
// there.
|
||||
// the transaction hash.
|
||||
nsDataHashtable<nsUint32HashKey, SpdyStream3 *> mStreamIDHash;
|
||||
nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
|
||||
SpdyStream3> mStreamTransactionHash;
|
||||
nsDeque mReadyForWrite;
|
||||
nsDeque mQueuedStreams;
|
||||
|
||||
// UrgentForWrite is meant to carry window updates. They were defined in
|
||||
// the v2 spec but apparently never implemented so are now scheduled to
|
||||
// be removed. But they will be reintroduced for v3, so we will leave
|
||||
// this queue in place to ease that transition.
|
||||
nsDeque mUrgentForWrite;
|
||||
|
||||
// Compression contexts for header transport using deflate.
|
||||
// SPDY compresses only HTTP headers and does not reset zlib in between
|
||||
// frames.
|
||||
// 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;
|
||||
|
||||
|
@ -308,15 +311,8 @@ private:
|
|||
// This reason code in the last processed RESET frame
|
||||
PRUint32 mDownstreamRstReason;
|
||||
|
||||
// These are used for decompressing downstream spdy response headers
|
||||
// This is done at the session level because sometimes the stream
|
||||
// has already been canceled but the decompression still must happen
|
||||
// to keep the zlib state correct for the next state of headers.
|
||||
PRUint32 mDecompressBufferSize;
|
||||
PRUint32 mDecompressBufferUsed;
|
||||
nsAutoArrayPtr<char> mDecompressBuffer;
|
||||
|
||||
// for the conversion of downstream http headers into spdy formatted headers
|
||||
// The data here does not persist between frames
|
||||
nsCString mFlatHTTPResponseHeaders;
|
||||
PRUint32 mFlatHTTPResponseHeadersOut;
|
||||
|
||||
|
@ -333,6 +329,11 @@ private:
|
|||
// 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.)
|
||||
PRUint32 mGoAwayID;
|
||||
|
@ -350,6 +351,9 @@ private:
|
|||
// The number of server initiated SYN-STREAMS, tracked for telemetry
|
||||
PRUint32 mServerPushedResources;
|
||||
|
||||
// The server rwin for new streams as determined from a SETTINGS frame
|
||||
PRUint32 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.
|
||||
|
|
|
@ -295,7 +295,7 @@ SpdyStream2::ParseHttpRequestHeaders(const char *buf,
|
|||
// Priority flags are the C0 mask of byte 16.
|
||||
//
|
||||
// The other 6 bits of 16 are unused. Spdy/3 will expand
|
||||
// priority to 4 bits.
|
||||
// priority to 3 bits.
|
||||
//
|
||||
// When Spdy/3 implements WINDOW_UPDATE the lowest priority
|
||||
// streams over a threshold (32?) should be given tiny
|
||||
|
|
|
@ -75,12 +75,19 @@ SpdyStream3::SpdyStream3(nsAHttpTransaction *httpTransaction,
|
|||
mRecvdFin(0),
|
||||
mFullyOpen(0),
|
||||
mSentWaitingFor(0),
|
||||
mReceivedData(0),
|
||||
mTxInlineFrameSize(SpdySession3::kDefaultBufferSize),
|
||||
mTxInlineFrameUsed(0),
|
||||
mTxStreamFrameSize(0),
|
||||
mZlib(compressionContext),
|
||||
mDecompressBufferSize(SpdySession3::kDefaultBufferSize),
|
||||
mDecompressBufferUsed(0),
|
||||
mDecompressedBytes(0),
|
||||
mRequestBodyLenRemaining(0),
|
||||
mPriority(priority),
|
||||
mLocalWindow(SpdySession3::kInitialRwin),
|
||||
mLocalUnacked(0),
|
||||
mBlockedOnRwin(false),
|
||||
mTotalSent(0),
|
||||
mTotalRead(0)
|
||||
{
|
||||
|
@ -88,7 +95,9 @@ SpdyStream3::SpdyStream3(nsAHttpTransaction *httpTransaction,
|
|||
|
||||
LOG3(("SpdyStream3::SpdyStream3 %p", this));
|
||||
|
||||
mRemoteWindow = spdySession->GetServerInitialWindow();
|
||||
mTxInlineFrame = new char[mTxInlineFrameSize];
|
||||
mDecompressBuffer = new char[mDecompressBufferSize];
|
||||
}
|
||||
|
||||
SpdyStream3::~SpdyStream3()
|
||||
|
@ -143,9 +152,12 @@ SpdyStream3::ReadSegments(nsAHttpSegmentReader *reader,
|
|||
if (rv == NS_BASE_STREAM_WOULD_BLOCK && !mTxInlineFrameUsed)
|
||||
mRequestBlockedOnRead = 1;
|
||||
|
||||
if (!mTxInlineFrameUsed && NS_SUCCEEDED(rv) && (!*countRead)) {
|
||||
LOG3(("ReadSegments %p: Sending request data complete, mUpstreamState=%x",
|
||||
this, mUpstreamState));
|
||||
// If the sending flow control window is open (!mBlockedOnRwin) then
|
||||
// continue sending the request
|
||||
if (!mBlockedOnRwin &&
|
||||
!mTxInlineFrameUsed && NS_SUCCEEDED(rv) && (!*countRead)) {
|
||||
LOG3(("SpdyStream3::ReadSegments %p 0x%X: Sending request data complete, "
|
||||
"mUpstreamState=%x",this, mStreamID, mUpstreamState));
|
||||
if (mSentFinOnData) {
|
||||
ChangeState(UPSTREAM_COMPLETE);
|
||||
}
|
||||
|
@ -156,7 +168,6 @@ SpdyStream3::ReadSegments(nsAHttpSegmentReader *reader,
|
|||
rv = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SENDING_SYN_STREAM:
|
||||
|
@ -313,7 +324,7 @@ SpdyStream3::ParseHttpRequestHeaders(const char *buf,
|
|||
// of SPDY headers.. writing to mTxInlineFrame{sz}
|
||||
|
||||
mTxInlineFrame[0] = SpdySession3::kFlag_Control;
|
||||
mTxInlineFrame[1] = 2; /* version */
|
||||
mTxInlineFrame[1] = SpdySession3::kVersion;
|
||||
mTxInlineFrame[2] = 0;
|
||||
mTxInlineFrame[3] = SpdySession3::CONTROL_TYPE_SYN_STREAM;
|
||||
// 4 to 7 are length and flags, we'll fill that in later
|
||||
|
@ -325,25 +336,32 @@ SpdyStream3::ParseHttpRequestHeaders(const char *buf,
|
|||
// from the client in the http binding
|
||||
memset (mTxInlineFrame + 12, 0, 4);
|
||||
|
||||
// Priority flags are the C0 mask of byte 16.
|
||||
//
|
||||
// The other 6 bits of 16 are unused. Spdy/3 will expand
|
||||
// priority to 4 bits.
|
||||
//
|
||||
// When Spdy/3 implements WINDOW_UPDATE the lowest priority
|
||||
// streams over a threshold (32?) should be given tiny
|
||||
// receive windows, separate from their spdy priority
|
||||
//
|
||||
if (mPriority >= nsISupportsPriority::PRIORITY_LOW)
|
||||
mTxInlineFrame[16] = SpdySession3::kPri03;
|
||||
else if (mPriority >= nsISupportsPriority::PRIORITY_NORMAL)
|
||||
mTxInlineFrame[16] = SpdySession3::kPri02;
|
||||
else if (mPriority >= nsISupportsPriority::PRIORITY_HIGH)
|
||||
mTxInlineFrame[16] = SpdySession3::kPri01;
|
||||
else
|
||||
mTxInlineFrame[16] = SpdySession3::kPri00;
|
||||
// Priority flags are the E0 mask of byte 16.
|
||||
// 0 is highest priority, 7 is lowest.
|
||||
// The other 5 bits of byte 16 are unused.
|
||||
|
||||
if (mPriority >= nsISupportsPriority::PRIORITY_LOWEST)
|
||||
mTxInlineFrame[16] = 7 << 5;
|
||||
else if (mPriority <= nsISupportsPriority::PRIORITY_HIGHEST)
|
||||
mTxInlineFrame[16] = 0 << 5;
|
||||
else {
|
||||
// The priority mapping relies on the unfiltered ranged to be
|
||||
// between -20 .. +20
|
||||
PR_STATIC_ASSERT(nsISupportsPriority::PRIORITY_LOWEST == 20);
|
||||
PR_STATIC_ASSERT(nsISupportsPriority::PRIORITY_HIGHEST == -20);
|
||||
|
||||
mTxInlineFrame[17] = 0; /* unused */
|
||||
// Add one to the priority so that values such as -10 and -11
|
||||
// get different spdy priorities - this appears to be an important
|
||||
// breaking line in the priorities content assigns to
|
||||
// transactions.
|
||||
PRUint8 calculatedPriority = 3 + ((mPriority + 1) / 5);
|
||||
NS_ABORT_IF_FALSE (!(calculatedPriority & 0xf8),
|
||||
"Calculated Priority Out Of Range");
|
||||
mTxInlineFrame[16] = calculatedPriority << 5;
|
||||
}
|
||||
|
||||
// The client cert "slot". Right now we don't send client certs
|
||||
mTxInlineFrame[17] = 0;
|
||||
|
||||
const char *methodHeader = mTransaction->RequestHead()->Method().get();
|
||||
|
||||
|
@ -386,17 +404,16 @@ SpdyStream3::ParseHttpRequestHeaders(const char *buf,
|
|||
// all header names are lower case in spdy
|
||||
ToLowerCase(name);
|
||||
|
||||
if (name.Equals("method") ||
|
||||
name.Equals("version") ||
|
||||
name.Equals("scheme") ||
|
||||
// exclusions.. mostly from 3.2.1
|
||||
if (name.Equals("connection") ||
|
||||
name.Equals("keep-alive") ||
|
||||
name.Equals("host") ||
|
||||
name.Equals("proxy-connection") ||
|
||||
name.Equals("accept-encoding") ||
|
||||
name.Equals("te") ||
|
||||
name.Equals("connection") ||
|
||||
name.Equals("proxy-connection") ||
|
||||
name.Equals("url"))
|
||||
name.Equals("transfer-encoding"))
|
||||
continue;
|
||||
|
||||
|
||||
nsCString *val = hdrHash.Get(name);
|
||||
if (!val) {
|
||||
val = new nsCString();
|
||||
|
@ -427,20 +444,23 @@ SpdyStream3::ParseHttpRequestHeaders(const char *buf,
|
|||
// headers at this same level so it is not necessary to do so here.
|
||||
|
||||
// The header block length
|
||||
PRUint16 count = hdrHash.Count() + 4; /* method, scheme, url, version */
|
||||
PRUint16 count = hdrHash.Count() + 5; /* method, path, version, host, scheme */
|
||||
CompressToFrame(count);
|
||||
|
||||
// method, scheme, url, and version headers for request line
|
||||
|
||||
CompressToFrame(NS_LITERAL_CSTRING("method"));
|
||||
// :method, :path, :version comprise a HTTP/1 request line, so send those first
|
||||
// to make life easy for any gateways
|
||||
CompressToFrame(NS_LITERAL_CSTRING(":method"));
|
||||
CompressToFrame(methodHeader, strlen(methodHeader));
|
||||
CompressToFrame(NS_LITERAL_CSTRING("scheme"));
|
||||
CompressToFrame(NS_LITERAL_CSTRING("https"));
|
||||
CompressToFrame(NS_LITERAL_CSTRING("url"));
|
||||
CompressToFrame(NS_LITERAL_CSTRING(":path"));
|
||||
CompressToFrame(mTransaction->RequestHead()->RequestURI());
|
||||
CompressToFrame(NS_LITERAL_CSTRING("version"));
|
||||
CompressToFrame(NS_LITERAL_CSTRING(":version"));
|
||||
CompressToFrame(versionHeader);
|
||||
|
||||
|
||||
CompressToFrame(NS_LITERAL_CSTRING(":host"));
|
||||
CompressToFrame(hostHeader);
|
||||
CompressToFrame(NS_LITERAL_CSTRING(":scheme"));
|
||||
CompressToFrame(NS_LITERAL_CSTRING("https"));
|
||||
|
||||
hdrHash.Enumerate(hdrHashEnumerate, this);
|
||||
CompressFlushFrame();
|
||||
|
||||
|
@ -678,26 +698,188 @@ SpdyStream3::CompressToFrame(const nsACString *str)
|
|||
}
|
||||
|
||||
// Dictionary taken from
|
||||
// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2
|
||||
// Name/Value Header Block Format
|
||||
// spec indicates that the compression dictionary is not null terminated
|
||||
// but in reality it is. see:
|
||||
// https://groups.google.com/forum/#!topic/spdy-dev/2pWxxOZEIcs
|
||||
// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
|
||||
|
||||
const char *SpdyStream3::kDictionary =
|
||||
"optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
|
||||
"languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
|
||||
"f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
|
||||
"-agent10010120020120220320420520630030130230330430530630740040140240340440"
|
||||
"5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
|
||||
"glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
|
||||
"ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
|
||||
"sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
|
||||
"oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
|
||||
"ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
|
||||
"pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
|
||||
"ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
|
||||
".1statusversionurl";
|
||||
const unsigned char SpdyStream3::kDictionary[] = {
|
||||
0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // - - - - o p t i
|
||||
0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // o n s - - - - h
|
||||
0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // e a d - - - - p
|
||||
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // o s t - - - - p
|
||||
0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // u t - - - - d e
|
||||
0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // l e t e - - - -
|
||||
0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // t r a c e - - -
|
||||
0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // - a c c e p t -
|
||||
0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p
|
||||
0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t - c h a r s e
|
||||
0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t - - - - a c c
|
||||
0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e p t - e n c o
|
||||
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // d i n g - - - -
|
||||
0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // a c c e p t - l
|
||||
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // a n g u a g e -
|
||||
0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p
|
||||
0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t - r a n g e s
|
||||
0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // - - - - a g e -
|
||||
0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // - - - a l l o w
|
||||
0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // - - - - a u t h
|
||||
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // o r i z a t i o
|
||||
0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n - - - - c a c
|
||||
0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // h e - c o n t r
|
||||
0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // o l - - - - c o
|
||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // n n e c t i o n
|
||||
0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // e n t - b a s e
|
||||
0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e n t - e n c o
|
||||
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // d i n g - - - -
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // c o n t e n t -
|
||||
0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // l a n g u a g e
|
||||
0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // e n t - l e n g
|
||||
0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // t h - - - - c o
|
||||
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // n t e n t - l o
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // c a t i o n - -
|
||||
0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n
|
||||
0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t - m d 5 - - -
|
||||
0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // - c o n t e n t
|
||||
0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // - r a n g e - -
|
||||
0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n
|
||||
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t - t y p e - -
|
||||
0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // - - d a t e - -
|
||||
0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // - - e t a g - -
|
||||
0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // - - e x p e c t
|
||||
0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // - - - - e x p i
|
||||
0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // r e s - - - - f
|
||||
0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // r o m - - - - h
|
||||
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // o s t - - - - i
|
||||
0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f - m a t c h -
|
||||
0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // - - - i f - m o
|
||||
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // d i f i e d - s
|
||||
0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // i n c e - - - -
|
||||
0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // i f - n o n e -
|
||||
0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // m a t c h - - -
|
||||
0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // - i f - r a n g
|
||||
0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e - - - - i f -
|
||||
0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // u n m o d i f i
|
||||
0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // e d - s i n c e
|
||||
0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // - - - - l a s t
|
||||
0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // - m o d i f i e
|
||||
0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d - - - - l o c
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // a t i o n - - -
|
||||
0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // - m a x - f o r
|
||||
0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // w a r d s - - -
|
||||
0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // - p r a g m a -
|
||||
0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // - - - p r o x y
|
||||
0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // - a u t h e n t
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // i c a t e - - -
|
||||
0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // - p r o x y - a
|
||||
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // u t h o r i z a
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // t i o n - - - -
|
||||
0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // r a n g e - - -
|
||||
0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // - r e f e r e r
|
||||
0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // - - - - r e t r
|
||||
0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y - a f t e r -
|
||||
0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // - - - s e r v e
|
||||
0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r - - - - t e -
|
||||
0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // - - - t r a i l
|
||||
0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // e r - - - - t r
|
||||
0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // a n s f e r - e
|
||||
0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // n c o d i n g -
|
||||
0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // - - - u p g r a
|
||||
0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // d e - - - - u s
|
||||
0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // e r - a g e n t
|
||||
0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // - - - - v a r y
|
||||
0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // - - - - v i a -
|
||||
0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // - - - w a r n i
|
||||
0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // n g - - - - w w
|
||||
0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w - a u t h e n
|
||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // t i c a t e - -
|
||||
0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // - - m e t h o d
|
||||
0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // - - - - g e t -
|
||||
0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // - - - s t a t u
|
||||
0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s - - - - 2 0 0
|
||||
0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // - O K - - - - v
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // e r s i o n - -
|
||||
0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // - - H T T P - 1
|
||||
0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // - 1 - - - - u r
|
||||
0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l - - - - p u b
|
||||
0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // l i c - - - - s
|
||||
0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // e t - c o o k i
|
||||
0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e - - - - k e e
|
||||
0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p - a l i v e -
|
||||
0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // - - - o r i g i
|
||||
0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n 1 0 0 1 0 1 2
|
||||
0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 0 1 2 0 2 2 0 5
|
||||
0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 2 0 6 3 0 0 3 0
|
||||
0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 2 3 0 3 3 0 4 3
|
||||
0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 0 5 3 0 6 3 0 7
|
||||
0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 4 0 2 4 0 5 4 0
|
||||
0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 6 4 0 7 4 0 8 4
|
||||
0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 0 9 4 1 0 4 1 1
|
||||
0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 4 1 2 4 1 3 4 1
|
||||
0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 4 4 1 5 4 1 6 4
|
||||
0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 1 7 5 0 2 5 0 4
|
||||
0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 5 0 5 2 0 3 - N
|
||||
0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // o n - A u t h o
|
||||
0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // r i t a t i v e
|
||||
0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // - I n f o r m a
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // t i o n 2 0 4 -
|
||||
0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // N o - C o n t e
|
||||
0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // n t 3 0 1 - M o
|
||||
0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // v e d - P e r m
|
||||
0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // a n e n t l y 4
|
||||
0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 0 0 - B a d - R
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // e q u e s t 4 0
|
||||
0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1 - U n a u t h
|
||||
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // o r i z e d 4 0
|
||||
0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3 - F o r b i d
|
||||
0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // d e n 4 0 4 - N
|
||||
0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // o t - F o u n d
|
||||
0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 5 0 0 - I n t e
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // r n a l - S e r
|
||||
0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // v e r - E r r o
|
||||
0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r 5 0 1 - N o t
|
||||
0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // - I m p l e m e
|
||||
0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // n t e d 5 0 3 -
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // S e r v i c e -
|
||||
0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // U n a v a i l a
|
||||
0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // b l e J a n - F
|
||||
0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // e b - M a r - A
|
||||
0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // p r - M a y - J
|
||||
0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // u n - J u l - A
|
||||
0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // u g - S e p t -
|
||||
0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // O c t - N o v -
|
||||
0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // D e c - 0 0 - 0
|
||||
0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0 - 0 0 - M o n
|
||||
0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // - - T u e - - W
|
||||
0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // e d - - T h u -
|
||||
0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // - F r i - - S a
|
||||
0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t - - S u n - -
|
||||
0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // G M T c h u n k
|
||||
0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // e d - t e x t -
|
||||
0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // h t m l - i m a
|
||||
0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // g e - p n g - i
|
||||
0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // m a g e - j p g
|
||||
0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // - i m a g e - g
|
||||
0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // i f - a p p l i
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x
|
||||
0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // m l - a p p l i
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x
|
||||
0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // h t m l - x m l
|
||||
0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // - t e x t - p l
|
||||
0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // a i n - t e x t
|
||||
0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // - j a v a s c r
|
||||
0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // i p t - p u b l
|
||||
0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // i c p r i v a t
|
||||
0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // e m a x - a g e
|
||||
0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // - g z i p - d e
|
||||
0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // f l a t e - s d
|
||||
0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // c h c h a r s e
|
||||
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t - u t f - 8 c
|
||||
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // h a r s e t - i
|
||||
0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // s o - 8 8 5 9 -
|
||||
0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1 - u t f - - -
|
||||
0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // - e n q - 0 -
|
||||
};
|
||||
|
||||
// use for zlib data types
|
||||
void *
|
||||
|
@ -713,6 +895,239 @@ SpdyStream3::zlib_destructor(void *opaque, void *addr)
|
|||
moz_free(addr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyStream3::Uncompress(z_stream *context,
|
||||
char *blockStart,
|
||||
PRUint32 blockLen)
|
||||
{
|
||||
mDecompressedBytes += blockLen;
|
||||
|
||||
context->avail_in = blockLen;
|
||||
context->next_in = reinterpret_cast<unsigned char *>(blockStart);
|
||||
|
||||
do {
|
||||
context->next_out =
|
||||
reinterpret_cast<unsigned char *>(mDecompressBuffer.get()) +
|
||||
mDecompressBufferUsed;
|
||||
context->avail_out = mDecompressBufferSize - mDecompressBufferUsed;
|
||||
int zlib_rv = inflate(context, Z_NO_FLUSH);
|
||||
|
||||
if (zlib_rv == Z_NEED_DICT)
|
||||
inflateSetDictionary(context, kDictionary, sizeof(kDictionary));
|
||||
|
||||
if (zlib_rv == Z_DATA_ERROR || zlib_rv == Z_MEM_ERROR)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// zlib's inflate() decreases context->avail_out by the amount it places
|
||||
// in the output buffer
|
||||
|
||||
mDecompressBufferUsed += mDecompressBufferSize - mDecompressBufferUsed -
|
||||
context->avail_out;
|
||||
|
||||
// When there is no more output room, but input still available then
|
||||
// increase the output space
|
||||
if (zlib_rv == Z_OK &&
|
||||
!context->avail_out && context->avail_in) {
|
||||
LOG3(("SpdyStream3::Uncompress %p Large Headers - so far %d",
|
||||
this, mDecompressBufferSize));
|
||||
SpdySession3::EnsureBuffer(mDecompressBuffer,
|
||||
mDecompressBufferSize + 4096,
|
||||
mDecompressBufferUsed,
|
||||
mDecompressBufferSize);
|
||||
}
|
||||
}
|
||||
while (context->avail_in);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdyStream3::FindHeader(nsCString name,
|
||||
nsDependentCSubstring &value)
|
||||
{
|
||||
const unsigned char *nvpair = reinterpret_cast<unsigned char *>
|
||||
(mDecompressBuffer.get()) + 4;
|
||||
const unsigned char *lastHeaderByte = reinterpret_cast<unsigned char *>
|
||||
(mDecompressBuffer.get()) + mDecompressBufferUsed;
|
||||
if (lastHeaderByte < nvpair)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
PRUint32 numPairs =
|
||||
PR_ntohl(reinterpret_cast<PRUint32 *>(mDecompressBuffer.get())[0]);
|
||||
for (PRUint32 index = 0; index < numPairs; ++index) {
|
||||
if (lastHeaderByte < nvpair + 4)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
PRUint32 nameLen = (nvpair[0] << 24) + (nvpair[1] << 16) +
|
||||
(nvpair[2] << 8) + nvpair[3];
|
||||
if (lastHeaderByte < nvpair + 4 + nameLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
nsDependentCSubstring nameString =
|
||||
Substring(reinterpret_cast<const char *>(nvpair) + 4,
|
||||
reinterpret_cast<const char *>(nvpair) + 4 + nameLen);
|
||||
if (lastHeaderByte < nvpair + 8 + nameLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
PRUint32 valueLen = (nvpair[4 + nameLen] << 24) + (nvpair[5 + nameLen] << 16) +
|
||||
(nvpair[6 + nameLen] << 8) + nvpair[7 + nameLen];
|
||||
if (lastHeaderByte < nvpair + 8 + nameLen + valueLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (nameString.Equals(name)) {
|
||||
value.Assign(((char *)nvpair) + 8 + nameLen, valueLen);
|
||||
return NS_OK;
|
||||
}
|
||||
nvpair += 8 + nameLen + valueLen;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// ConvertHeaders is used to convert the response headers
|
||||
// in a syn_reply or in 0..N headers frames that follow it into
|
||||
// HTTP/1 format
|
||||
nsresult
|
||||
SpdyStream3::ConvertHeaders(nsACString &aHeadersOut)
|
||||
{
|
||||
// :status and :version are required.
|
||||
nsDependentCSubstring status, version;
|
||||
nsresult rv = FindHeader(NS_LITERAL_CSTRING(":status"),
|
||||
status);
|
||||
if (NS_FAILED(rv))
|
||||
return (rv == NS_ERROR_NOT_AVAILABLE) ? NS_ERROR_ILLEGAL_VALUE : rv;
|
||||
|
||||
rv = FindHeader(NS_LITERAL_CSTRING(":version"),
|
||||
version);
|
||||
if (NS_FAILED(rv))
|
||||
return (rv == NS_ERROR_NOT_AVAILABLE) ? NS_ERROR_ILLEGAL_VALUE : rv;
|
||||
|
||||
if (mDecompressedBytes && mDecompressBufferUsed) {
|
||||
Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_SIZE, mDecompressedBytes);
|
||||
PRUint32 ratio =
|
||||
mDecompressedBytes * 100 / mDecompressBufferUsed;
|
||||
Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_RATIO, ratio);
|
||||
}
|
||||
|
||||
aHeadersOut.Truncate();
|
||||
aHeadersOut.SetCapacity(mDecompressBufferUsed + 64);
|
||||
|
||||
// Connection, Keep-Alive and chunked transfer encodings are to be
|
||||
// removed.
|
||||
|
||||
// Content-Length is 'advisory'.. we will not strip it because it can
|
||||
// create UI feedback.
|
||||
|
||||
aHeadersOut.Append(version);
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING(" "));
|
||||
aHeadersOut.Append(status);
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING("\r\n"));
|
||||
|
||||
const unsigned char *nvpair = reinterpret_cast<unsigned char *>
|
||||
(mDecompressBuffer.get()) + 4;
|
||||
const unsigned char *lastHeaderByte = reinterpret_cast<unsigned char *>
|
||||
(mDecompressBuffer.get()) + mDecompressBufferUsed;
|
||||
|
||||
if (lastHeaderByte < nvpair)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
PRUint32 numPairs =
|
||||
PR_ntohl(reinterpret_cast<PRUint32 *>(mDecompressBuffer.get())[0]);
|
||||
|
||||
for (PRUint32 index = 0; index < numPairs; ++index) {
|
||||
if (lastHeaderByte < nvpair + 4)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
PRUint32 nameLen = (nvpair[0] << 24) + (nvpair[1] << 16) +
|
||||
(nvpair[2] << 8) + nvpair[3];
|
||||
if (lastHeaderByte < nvpair + 4 + nameLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
nsDependentCSubstring nameString =
|
||||
Substring(reinterpret_cast<const char *>(nvpair) + 4,
|
||||
reinterpret_cast<const char *>(nvpair) + 4 + nameLen);
|
||||
|
||||
if (lastHeaderByte < nvpair + 8 + nameLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
// Look for illegal characters in the nameString.
|
||||
// This includes upper case characters and nulls (as they will
|
||||
// break the fixup-nulls-in-value-string algorithm)
|
||||
// Look for upper case characters in the name. They are illegal.
|
||||
for (char *cPtr = nameString.BeginWriting();
|
||||
cPtr && cPtr < nameString.EndWriting();
|
||||
++cPtr) {
|
||||
if (*cPtr <= 'Z' && *cPtr >= 'A') {
|
||||
nsCString toLog(nameString);
|
||||
|
||||
LOG3(("SpdyStream3::ConvertHeaders session=%p stream=%p "
|
||||
"upper case response header found. [%s]\n",
|
||||
mSession, this, toLog.get()));
|
||||
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// check for null characters
|
||||
if (*cPtr == '\0')
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// HTTP Chunked responses are not legal over spdy. We do not need
|
||||
// to look for chunked specifically because it is the only HTTP
|
||||
// allowed default encoding and we did not negotiate further encodings
|
||||
// via TE
|
||||
if (nameString.Equals(NS_LITERAL_CSTRING("transfer-encoding"))) {
|
||||
LOG3(("SpdyStream3::ConvertHeaders session=%p stream=%p "
|
||||
"transfer-encoding found. Chunked is invalid and no TE sent.",
|
||||
mSession, this));
|
||||
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
PRUint32 valueLen =
|
||||
(nvpair[4 + nameLen] << 24) + (nvpair[5 + nameLen] << 16) +
|
||||
(nvpair[6 + nameLen] << 8) + nvpair[7 + nameLen];
|
||||
|
||||
if (lastHeaderByte < nvpair + 8 + nameLen + valueLen)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (!nameString.Equals(NS_LITERAL_CSTRING(":version")) &&
|
||||
!nameString.Equals(NS_LITERAL_CSTRING(":status")) &&
|
||||
!nameString.Equals(NS_LITERAL_CSTRING("connection")) &&
|
||||
!nameString.Equals(NS_LITERAL_CSTRING("keep-alive"))) {
|
||||
nsDependentCSubstring valueString =
|
||||
Substring(reinterpret_cast<const char *>(nvpair) + 8 + nameLen,
|
||||
reinterpret_cast<const char *>(nvpair) + 8 + nameLen +
|
||||
valueLen);
|
||||
|
||||
aHeadersOut.Append(nameString);
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING(": "));
|
||||
|
||||
// expand NULL bytes in the value string
|
||||
for (char *cPtr = valueString.BeginWriting();
|
||||
cPtr && cPtr < valueString.EndWriting();
|
||||
++cPtr) {
|
||||
if (*cPtr != 0) {
|
||||
aHeadersOut.Append(*cPtr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// NULLs are really "\r\nhdr: "
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING("\r\n"));
|
||||
aHeadersOut.Append(nameString);
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING(": "));
|
||||
}
|
||||
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING("\r\n"));
|
||||
}
|
||||
nvpair += 8 + nameLen + valueLen;
|
||||
}
|
||||
|
||||
aHeadersOut.Append(NS_LITERAL_CSTRING("X-Firefox-Spdy: 3\r\n\r\n"));
|
||||
LOG (("decoded response headers are:\n%s",
|
||||
aHeadersOut.BeginReading()));
|
||||
|
||||
// The spdy formatted buffer isnt needed anymore - free it up
|
||||
mDecompressBuffer = nsnull;
|
||||
mDecompressBufferSize = 0;
|
||||
mDecompressBufferUsed = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyStream3::ExecuteCompress(PRUint32 flushMode)
|
||||
{
|
||||
|
@ -739,15 +1154,14 @@ SpdyStream3::ExecuteCompress(PRUint32 flushMode)
|
|||
}
|
||||
|
||||
void
|
||||
SpdyStream3::CompressToFrame(PRUint16 data)
|
||||
SpdyStream3::CompressToFrame(PRUint32 data)
|
||||
{
|
||||
// convert the data to network byte order and write that
|
||||
// convert the data to 4 byte network byte order and write that
|
||||
// to the compressed stream
|
||||
|
||||
data = PR_htons(data);
|
||||
data = PR_htonl(data);
|
||||
|
||||
mZlib->next_in = reinterpret_cast<unsigned char *> (&data);
|
||||
mZlib->avail_in = 2;
|
||||
mZlib->avail_in = 4;
|
||||
ExecuteCompress(Z_NO_FLUSH);
|
||||
}
|
||||
|
||||
|
@ -755,19 +1169,14 @@ SpdyStream3::CompressToFrame(PRUint16 data)
|
|||
void
|
||||
SpdyStream3::CompressToFrame(const char *data, PRUint32 len)
|
||||
{
|
||||
// Format calls for a network ordered 16 bit length
|
||||
// Format calls for a network ordered 32 bit length
|
||||
// followed by the utf8 string
|
||||
|
||||
// for now, silently truncate headers greater than 64KB. Spdy/3 will
|
||||
// fix this by making the len a 32 bit quantity
|
||||
if (len > 0xffff)
|
||||
len = 0xffff;
|
||||
|
||||
PRUint16 networkLen = PR_htons(len);
|
||||
PRUint32 networkLen = PR_htonl(len);
|
||||
|
||||
// write out the length
|
||||
mZlib->next_in = reinterpret_cast<unsigned char *> (&networkLen);
|
||||
mZlib->avail_in = 2;
|
||||
mZlib->avail_in = 4;
|
||||
ExecuteCompress(Z_NO_FLUSH);
|
||||
|
||||
// write out the data
|
||||
|
@ -854,7 +1263,24 @@ SpdyStream3::OnReadSegment(const char *buf,
|
|||
break;
|
||||
|
||||
case GENERATING_REQUEST_BODY:
|
||||
if (mRemoteWindow <= 0) {
|
||||
*countRead = 0;
|
||||
LOG3(("SpdyStream3 this=%p, id 0x%X request body suspended because "
|
||||
"remote window is %d.\n", this, mStreamID, mRemoteWindow));
|
||||
mBlockedOnRwin = true;
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
mBlockedOnRwin = false;
|
||||
|
||||
dataLength = NS_MIN(count, mChunkSize);
|
||||
|
||||
if (dataLength > mRemoteWindow)
|
||||
dataLength = mRemoteWindow;
|
||||
|
||||
LOG3(("SpdyStream3 this=%p id 0x%X remote window is %d. Chunk is %d\n",
|
||||
this, mStreamID, mRemoteWindow, dataLength));
|
||||
mRemoteWindow -= dataLength;
|
||||
|
||||
LOG3(("SpdyStream3 %p id %x request len remaining %d, "
|
||||
"count avail %d, chunk used %d",
|
||||
this, mStreamID, mRequestBodyLenRemaining, count, dataLength));
|
||||
|
|
|
@ -83,15 +83,37 @@ public:
|
|||
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(PRUint32 count);
|
||||
void UpdateTransportReadEvents(PRUint32 count);
|
||||
|
||||
// The zlib header compression dictionary defined by SPDY,
|
||||
// and hooks to the mozilla allocator for zlib to use.
|
||||
static const char *kDictionary;
|
||||
static const unsigned char kDictionary[1423];
|
||||
static void *zlib_allocator(void *, uInt, uInt);
|
||||
static void zlib_destructor(void *, void *);
|
||||
|
||||
nsresult Uncompress(z_stream *, char *, PRUint32);
|
||||
nsresult ConvertHeaders(nsACString &);
|
||||
|
||||
void UpdateRemoteWindow(PRInt32 delta) { mRemoteWindow += delta; }
|
||||
PRInt64 RemoteWindow() { return mRemoteWindow; }
|
||||
|
||||
void DecrementLocalWindow(PRUint32 delta) {
|
||||
mLocalWindow -= delta;
|
||||
mLocalUnacked += delta;
|
||||
}
|
||||
|
||||
void IncrementLocalWindow(PRUint32 delta) {
|
||||
mLocalWindow += delta;
|
||||
mLocalUnacked -= delta;
|
||||
}
|
||||
|
||||
PRUint64 LocalUnAcked() { return mLocalUnacked; }
|
||||
bool BlockedOnRwin() { return mBlockedOnRwin; }
|
||||
|
||||
private:
|
||||
|
||||
// a SpdyStream3 object is only destroyed by being removed from the
|
||||
|
@ -121,9 +143,10 @@ private:
|
|||
void CompressToFrame(const nsACString &);
|
||||
void CompressToFrame(const nsACString *);
|
||||
void CompressToFrame(const char *, PRUint32);
|
||||
void CompressToFrame(PRUint16);
|
||||
void CompressToFrame(PRUint32);
|
||||
void CompressFlushFrame();
|
||||
void ExecuteCompress(PRUint32);
|
||||
nsresult FindHeader(nsCString, nsDependentCSubstring &);
|
||||
|
||||
// Each stream goes from syn_stream to upstream_complete, perhaps
|
||||
// looping on multiple instances of generating_request_body and
|
||||
|
@ -175,6 +198,10 @@ private:
|
|||
// Flag is set after the WAITING_FOR Transport event has been generated
|
||||
PRUint32 mSentWaitingFor : 1;
|
||||
|
||||
// Flag is set after 1st DATA frame has been passed to stream, after
|
||||
// which additional HEADERS data is invalid
|
||||
PRUint32 mReceivedData : 1;
|
||||
|
||||
// The InlineFrame and associated data is used for composing control
|
||||
// frames and data frame headers.
|
||||
nsAutoArrayPtr<char> mTxInlineFrame;
|
||||
|
@ -192,6 +219,12 @@ private:
|
|||
z_stream *mZlib;
|
||||
nsCString mFlatHttpRequestHeaders;
|
||||
|
||||
// These are used for decompressing downstream spdy response headers
|
||||
PRUint32 mDecompressBufferSize;
|
||||
PRUint32 mDecompressBufferUsed;
|
||||
PRUint32 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
|
||||
|
@ -202,6 +235,27 @@ private:
|
|||
// based on nsISupportsPriority definitions
|
||||
PRInt32 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
|
||||
PRInt64 mLocalWindow;
|
||||
|
||||
// RemoteWindow is how much data the client is allowed to send without
|
||||
// getting a window update
|
||||
PRInt64 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
|
||||
PRUint64 mLocalUnacked;
|
||||
|
||||
// True when sending is suspended becuase the remote flow control window is
|
||||
// <= 0
|
||||
bool mBlockedOnRwin;
|
||||
|
||||
// For Progress Events
|
||||
PRUint64 mTotalSent;
|
||||
PRUint64 mTotalRead;
|
||||
|
|
Загрузка…
Ссылка в новой задаче