1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/http/SpdyStream31.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,255 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_net_SpdyStream31_h 1.10 +#define mozilla_net_SpdyStream31_h 1.11 + 1.12 +#include "mozilla/Attributes.h" 1.13 +#include "nsAHttpTransaction.h" 1.14 + 1.15 +namespace mozilla { namespace net { 1.16 + 1.17 +class SpdyStream31 : public nsAHttpSegmentReader 1.18 + , public nsAHttpSegmentWriter 1.19 +{ 1.20 +public: 1.21 + NS_DECL_NSAHTTPSEGMENTREADER 1.22 + NS_DECL_NSAHTTPSEGMENTWRITER 1.23 + 1.24 + SpdyStream31(nsAHttpTransaction *, SpdySession31 *, int32_t); 1.25 + 1.26 + uint32_t StreamID() { return mStreamID; } 1.27 + SpdyPushedStream31 *PushSource() { return mPushSource; } 1.28 + 1.29 + virtual nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *); 1.30 + virtual nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *); 1.31 + virtual bool DeferCleanupOnSuccess() { return false; } 1.32 + 1.33 + const nsAFlatCString &Origin() const { return mOrigin; } 1.34 + 1.35 + bool RequestBlockedOnRead() 1.36 + { 1.37 + return static_cast<bool>(mRequestBlockedOnRead); 1.38 + } 1.39 + 1.40 + // returns false if called more than once 1.41 + bool GetFullyOpen() {return mFullyOpen;} 1.42 + void SetFullyOpen() 1.43 + { 1.44 + MOZ_ASSERT(!mFullyOpen); 1.45 + mFullyOpen = 1; 1.46 + } 1.47 + 1.48 + bool HasRegisteredID() { return mStreamID != 0; } 1.49 + 1.50 + nsAHttpTransaction *Transaction() { return mTransaction; } 1.51 + virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() 1.52 + { 1.53 + return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr; 1.54 + } 1.55 + 1.56 + void Close(nsresult reason); 1.57 + 1.58 + void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; } 1.59 + bool RecvdFin() { return mRecvdFin; } 1.60 + 1.61 + void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; } 1.62 + bool RecvdData() { return mReceivedData; } 1.63 + 1.64 + void UpdateTransportSendEvents(uint32_t count); 1.65 + void UpdateTransportReadEvents(uint32_t count); 1.66 + 1.67 + // The zlib header compression dictionary defined by SPDY. 1.68 + static const unsigned char kDictionary[1423]; 1.69 + 1.70 + nsresult Uncompress(z_stream *, char *, uint32_t); 1.71 + nsresult ConvertHeaders(nsACString &); 1.72 + 1.73 + void UpdateRemoteWindow(int32_t delta); 1.74 + int64_t RemoteWindow() { return mRemoteWindow; } 1.75 + 1.76 + void DecrementLocalWindow(uint32_t delta) { 1.77 + mLocalWindow -= delta; 1.78 + mLocalUnacked += delta; 1.79 + } 1.80 + 1.81 + void IncrementLocalWindow(uint32_t delta) { 1.82 + mLocalWindow += delta; 1.83 + mLocalUnacked -= delta; 1.84 + } 1.85 + 1.86 + uint64_t LocalUnAcked() { return mLocalUnacked; } 1.87 + int64_t LocalWindow() { return mLocalWindow; } 1.88 + 1.89 + bool BlockedOnRwin() { return mBlockedOnRwin; } 1.90 + 1.91 + // A pull stream has an implicit sink, a pushed stream has a sink 1.92 + // once it is matched to a pull stream. 1.93 + virtual bool HasSink() { return true; } 1.94 + 1.95 + virtual ~SpdyStream31(); 1.96 + 1.97 +protected: 1.98 + nsresult FindHeader(nsCString, nsDependentCSubstring &); 1.99 + 1.100 + static void CreatePushHashKey(const nsCString &scheme, 1.101 + const nsCString &hostHeader, 1.102 + uint64_t serial, 1.103 + const nsCSubstring &pathInfo, 1.104 + nsCString &outOrigin, 1.105 + nsCString &outKey); 1.106 + 1.107 + enum stateType { 1.108 + GENERATING_SYN_STREAM, 1.109 + GENERATING_REQUEST_BODY, 1.110 + SENDING_REQUEST_BODY, 1.111 + SENDING_FIN_STREAM, 1.112 + UPSTREAM_COMPLETE 1.113 + }; 1.114 + 1.115 + uint32_t mStreamID; 1.116 + 1.117 + // The session that this stream is a subset of 1.118 + SpdySession31 *mSession; 1.119 + 1.120 + nsCString mOrigin; 1.121 + 1.122 + // Each stream goes from syn_stream to upstream_complete, perhaps 1.123 + // looping on multiple instances of generating_request_body and 1.124 + // sending_request_body for each SPDY chunk in the upload. 1.125 + enum stateType mUpstreamState; 1.126 + 1.127 + // Flag is set when all http request headers have been read and ID is stable 1.128 + uint32_t mSynFrameComplete : 1; 1.129 + 1.130 + // Flag is set when a FIN has been placed on a data or syn packet 1.131 + // (i.e after the client has closed) 1.132 + uint32_t mSentFinOnData : 1; 1.133 + 1.134 + void ChangeState(enum stateType); 1.135 + 1.136 +private: 1.137 + friend class nsAutoPtr<SpdyStream31>; 1.138 + 1.139 + static PLDHashOperator hdrHashEnumerate(const nsACString &, 1.140 + nsAutoPtr<nsCString> &, 1.141 + void *); 1.142 + 1.143 + nsresult ParseHttpRequestHeaders(const char *, uint32_t, uint32_t *); 1.144 + void AdjustInitialWindow(); 1.145 + nsresult TransmitFrame(const char *, uint32_t *, bool forceCommitment); 1.146 + void GenerateDataFrameHeader(uint32_t, bool); 1.147 + 1.148 + void CompressToFrame(const nsACString &); 1.149 + void CompressToFrame(const nsACString *); 1.150 + void CompressToFrame(const char *, uint32_t); 1.151 + void CompressToFrame(uint32_t); 1.152 + void CompressFlushFrame(); 1.153 + void ExecuteCompress(uint32_t); 1.154 + 1.155 + // The underlying HTTP transaction. This pointer is used as the key 1.156 + // in the SpdySession31 mStreamTransactionHash so it is important to 1.157 + // keep a reference to it as long as this stream is a member of that hash. 1.158 + // (i.e. don't change it or release it after it is set in the ctor). 1.159 + nsRefPtr<nsAHttpTransaction> mTransaction; 1.160 + 1.161 + // The underlying socket transport object is needed to propogate some events 1.162 + nsISocketTransport *mSocketTransport; 1.163 + 1.164 + // These are temporary state variables to hold the argument to 1.165 + // Read/WriteSegments so it can be accessed by On(read/write)segment 1.166 + // further up the stack. 1.167 + nsAHttpSegmentReader *mSegmentReader; 1.168 + nsAHttpSegmentWriter *mSegmentWriter; 1.169 + 1.170 + // The quanta upstream data frames are chopped into 1.171 + uint32_t mChunkSize; 1.172 + 1.173 + // Flag is set when the HTTP processor has more data to send 1.174 + // but has blocked in doing so. 1.175 + uint32_t mRequestBlockedOnRead : 1; 1.176 + 1.177 + // Flag is set after the response frame bearing the fin bit has 1.178 + // been processed. (i.e. after the server has closed). 1.179 + uint32_t mRecvdFin : 1; 1.180 + 1.181 + // Flag is set after syn reply received 1.182 + uint32_t mFullyOpen : 1; 1.183 + 1.184 + // Flag is set after the WAITING_FOR Transport event has been generated 1.185 + uint32_t mSentWaitingFor : 1; 1.186 + 1.187 + // Flag is set after 1st DATA frame has been passed to stream, after 1.188 + // which additional HEADERS data is invalid 1.189 + uint32_t mReceivedData : 1; 1.190 + 1.191 + // Flag is set after TCP send autotuning has been disabled 1.192 + uint32_t mSetTCPSocketBuffer : 1; 1.193 + 1.194 + // The InlineFrame and associated data is used for composing control 1.195 + // frames and data frame headers. 1.196 + nsAutoArrayPtr<uint8_t> mTxInlineFrame; 1.197 + uint32_t mTxInlineFrameSize; 1.198 + uint32_t mTxInlineFrameUsed; 1.199 + 1.200 + // mTxStreamFrameSize tracks the progress of 1.201 + // transmitting a request body data frame. The data frame itself 1.202 + // is never copied into the spdy layer. 1.203 + uint32_t mTxStreamFrameSize; 1.204 + 1.205 + // Compression context and buffer for request header compression. 1.206 + // This is a copy of SpdySession31::mUpstreamZlib because it needs 1.207 + // to remain the same in all streams of a session. 1.208 + z_stream *mZlib; 1.209 + nsCString mFlatHttpRequestHeaders; 1.210 + 1.211 + // These are used for decompressing downstream spdy response headers 1.212 + uint32_t mDecompressBufferSize; 1.213 + uint32_t mDecompressBufferUsed; 1.214 + uint32_t mDecompressedBytes; 1.215 + nsAutoArrayPtr<char> mDecompressBuffer; 1.216 + 1.217 + // Track the content-length of a request body so that we can 1.218 + // place the fin flag on the last data packet instead of waiting 1.219 + // for a stream closed indication. Relying on stream close results 1.220 + // in an extra 0-length runt packet and seems to have some interop 1.221 + // problems with the google servers. 1.222 + int64_t mRequestBodyLenRemaining; 1.223 + 1.224 + // based on nsISupportsPriority definitions 1.225 + int32_t mPriority; 1.226 + 1.227 + // mLocalWindow, mRemoteWindow, and mLocalUnacked are for flow control. 1.228 + // *window are signed because the race conditions in asynchronous SETTINGS 1.229 + // messages can force them temporarily negative. 1.230 + 1.231 + // LocalWindow is how much data the server will send without getting a 1.232 + // window update 1.233 + int64_t mLocalWindow; 1.234 + 1.235 + // RemoteWindow is how much data the client is allowed to send without 1.236 + // getting a window update 1.237 + int64_t mRemoteWindow; 1.238 + 1.239 + // LocalUnacked is the number of bytes received by the client but not 1.240 + // yet reflected in a window update. Sending that update will increment 1.241 + // LocalWindow 1.242 + uint64_t mLocalUnacked; 1.243 + 1.244 + // True when sending is suspended becuase the remote flow control window is 1.245 + // <= 0 1.246 + bool mBlockedOnRwin; 1.247 + 1.248 + // For Progress Events 1.249 + uint64_t mTotalSent; 1.250 + uint64_t mTotalRead; 1.251 + 1.252 + // For SpdyPush 1.253 + SpdyPushedStream31 *mPushSource; 1.254 +}; 1.255 + 1.256 +}} // namespace mozilla::net 1.257 + 1.258 +#endif // mozilla_net_SpdyStream31_h