1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/http/Http2Stream.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,274 @@ 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_Http2Stream_h 1.10 +#define mozilla_net_Http2Stream_h 1.11 + 1.12 +#include "mozilla/Attributes.h" 1.13 +#include "nsAHttpTransaction.h" 1.14 +#include "nsISupportsPriority.h" 1.15 + 1.16 +namespace mozilla { 1.17 +namespace net { 1.18 + 1.19 +class Http2Session; 1.20 +class Http2Decompressor; 1.21 + 1.22 +class Http2Stream 1.23 + : public nsAHttpSegmentReader 1.24 + , public nsAHttpSegmentWriter 1.25 +{ 1.26 +public: 1.27 + NS_DECL_NSAHTTPSEGMENTREADER 1.28 + NS_DECL_NSAHTTPSEGMENTWRITER 1.29 + 1.30 + enum stateType { 1.31 + IDLE, 1.32 + RESERVED_BY_REMOTE, 1.33 + OPEN, 1.34 + CLOSED_BY_LOCAL, 1.35 + CLOSED_BY_REMOTE, 1.36 + CLOSED 1.37 + }; 1.38 + 1.39 + const static int32_t kNormalPriority = 0x1000; 1.40 + const static int32_t kWorstPriority = kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST; 1.41 + const static int32_t kBestPriority = kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST; 1.42 + 1.43 + Http2Stream(nsAHttpTransaction *, Http2Session *, int32_t); 1.44 + 1.45 + uint32_t StreamID() { return mStreamID; } 1.46 + Http2PushedStream *PushSource() { return mPushSource; } 1.47 + 1.48 + stateType HTTPState() { return mState; } 1.49 + void SetHTTPState(stateType val) { mState = val; } 1.50 + 1.51 + virtual nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *); 1.52 + virtual nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *); 1.53 + virtual bool DeferCleanupOnSuccess() { return false; } 1.54 + 1.55 + const nsAFlatCString &Origin() const { return mOrigin; } 1.56 + 1.57 + bool RequestBlockedOnRead() 1.58 + { 1.59 + return static_cast<bool>(mRequestBlockedOnRead); 1.60 + } 1.61 + 1.62 + bool HasRegisteredID() { return mStreamID != 0; } 1.63 + 1.64 + nsAHttpTransaction *Transaction() { return mTransaction; } 1.65 + virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() 1.66 + { 1.67 + return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr; 1.68 + } 1.69 + 1.70 + void Close(nsresult reason); 1.71 + 1.72 + void SetRecvdFin(bool aStatus); 1.73 + bool RecvdFin() { return mRecvdFin; } 1.74 + 1.75 + void SetSentFin(bool aStatus); 1.76 + bool SentFin() { return mSentFin; } 1.77 + 1.78 + void SetRecvdReset(bool aStatus); 1.79 + bool RecvdReset() { return mRecvdReset; } 1.80 + 1.81 + void SetSentReset(bool aStatus); 1.82 + bool SentReset() { return mSentReset; } 1.83 + 1.84 + void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; } 1.85 + bool CountAsActive() { return mCountAsActive; } 1.86 + 1.87 + void SetAllHeadersReceived(bool aStatus) { mAllHeadersReceived = aStatus ? 1 : 0; } 1.88 + bool AllHeadersReceived() { return mAllHeadersReceived; } 1.89 + 1.90 + void UpdateTransportSendEvents(uint32_t count); 1.91 + void UpdateTransportReadEvents(uint32_t count); 1.92 + 1.93 + nsresult ConvertResponseHeaders(Http2Decompressor *, nsACString &, nsACString &); 1.94 + nsresult ConvertPushHeaders(Http2Decompressor *, nsACString &, nsACString &); 1.95 + 1.96 + bool AllowFlowControlledWrite(); 1.97 + void UpdateServerReceiveWindow(int32_t delta); 1.98 + int64_t ServerReceiveWindow() { return mServerReceiveWindow; } 1.99 + 1.100 + void DecrementClientReceiveWindow(uint32_t delta) { 1.101 + mClientReceiveWindow -= delta; 1.102 + mLocalUnacked += delta; 1.103 + } 1.104 + 1.105 + void IncrementClientReceiveWindow(uint32_t delta) { 1.106 + mClientReceiveWindow += delta; 1.107 + mLocalUnacked -= delta; 1.108 + } 1.109 + 1.110 + uint64_t LocalUnAcked() { return mLocalUnacked; } 1.111 + int64_t ClientReceiveWindow() { return mClientReceiveWindow; } 1.112 + 1.113 + bool BlockedOnRwin() { return mBlockedOnRwin; } 1.114 + 1.115 + uint32_t Priority() { return mPriority; } 1.116 + void SetPriority(uint32_t); 1.117 + 1.118 + // A pull stream has an implicit sink, a pushed stream has a sink 1.119 + // once it is matched to a pull stream. 1.120 + virtual bool HasSink() { return true; } 1.121 + 1.122 + virtual ~Http2Stream(); 1.123 + 1.124 +protected: 1.125 + static void CreatePushHashKey(const nsCString &scheme, 1.126 + const nsCString &hostHeader, 1.127 + uint64_t serial, 1.128 + const nsCSubstring &pathInfo, 1.129 + nsCString &outOrigin, 1.130 + nsCString &outKey); 1.131 + 1.132 + // These internal states track request generation 1.133 + enum upstreamStateType { 1.134 + GENERATING_HEADERS, 1.135 + GENERATING_BODY, 1.136 + SENDING_BODY, 1.137 + SENDING_FIN_STREAM, 1.138 + UPSTREAM_COMPLETE 1.139 + }; 1.140 + 1.141 + uint32_t mStreamID; 1.142 + 1.143 + // The session that this stream is a subset of 1.144 + Http2Session *mSession; 1.145 + 1.146 + nsCString mOrigin; 1.147 + nsCString mHeaderHost; 1.148 + nsCString mHeaderScheme; 1.149 + nsCString mHeaderPath; 1.150 + 1.151 + // Each stream goes from generating_headers to upstream_complete, perhaps 1.152 + // looping on multiple instances of generating_body and 1.153 + // sending_body for each frame in the upload. 1.154 + enum upstreamStateType mUpstreamState; 1.155 + 1.156 + // The HTTP/2 state for the stream from section 5.1 1.157 + enum stateType mState; 1.158 + 1.159 + // Flag is set when all http request headers have been read and ID is stable 1.160 + uint32_t mAllHeadersSent : 1; 1.161 + 1.162 + // Flag is set when all http request headers have been read and ID is stable 1.163 + uint32_t mAllHeadersReceived : 1; 1.164 + 1.165 + void ChangeState(enum upstreamStateType); 1.166 + 1.167 +private: 1.168 + friend class nsAutoPtr<Http2Stream>; 1.169 + 1.170 + nsresult ParseHttpRequestHeaders(const char *, uint32_t, uint32_t *); 1.171 + void AdjustPushedPriority(); 1.172 + void AdjustInitialWindow(); 1.173 + nsresult TransmitFrame(const char *, uint32_t *, bool forceCommitment); 1.174 + void GenerateDataFrameHeader(uint32_t, bool); 1.175 + 1.176 + // The underlying HTTP transaction. This pointer is used as the key 1.177 + // in the Http2Session mStreamTransactionHash so it is important to 1.178 + // keep a reference to it as long as this stream is a member of that hash. 1.179 + // (i.e. don't change it or release it after it is set in the ctor). 1.180 + nsRefPtr<nsAHttpTransaction> mTransaction; 1.181 + 1.182 + // The underlying socket transport object is needed to propogate some events 1.183 + nsISocketTransport *mSocketTransport; 1.184 + 1.185 + // These are temporary state variables to hold the argument to 1.186 + // Read/WriteSegments so it can be accessed by On(read/write)segment 1.187 + // further up the stack. 1.188 + nsAHttpSegmentReader *mSegmentReader; 1.189 + nsAHttpSegmentWriter *mSegmentWriter; 1.190 + 1.191 + // The quanta upstream data frames are chopped into 1.192 + uint32_t mChunkSize; 1.193 + 1.194 + // Flag is set when the HTTP processor has more data to send 1.195 + // but has blocked in doing so. 1.196 + uint32_t mRequestBlockedOnRead : 1; 1.197 + 1.198 + // Flag is set after the response frame bearing the fin bit has 1.199 + // been processed. (i.e. after the server has closed). 1.200 + uint32_t mRecvdFin : 1; 1.201 + 1.202 + // Flag is set after RST_STREAM has been received for this stream 1.203 + uint32_t mRecvdReset : 1; 1.204 + 1.205 + // Flag is set after RST_STREAM has been generated for this stream 1.206 + uint32_t mSentReset : 1; 1.207 + 1.208 + // Flag is set when stream is counted towards MAX_CONCURRENT streams in session 1.209 + uint32_t mCountAsActive : 1; 1.210 + 1.211 + // Flag is set when a FIN has been placed on a data or header frame 1.212 + // (i.e after the client has closed) 1.213 + uint32_t mSentFin : 1; 1.214 + 1.215 + // Flag is set after the WAITING_FOR Transport event has been generated 1.216 + uint32_t mSentWaitingFor : 1; 1.217 + 1.218 + // Flag is set after TCP send autotuning has been disabled 1.219 + uint32_t mSetTCPSocketBuffer : 1; 1.220 + 1.221 + // The InlineFrame and associated data is used for composing control 1.222 + // frames and data frame headers. 1.223 + nsAutoArrayPtr<uint8_t> mTxInlineFrame; 1.224 + uint32_t mTxInlineFrameSize; 1.225 + uint32_t mTxInlineFrameUsed; 1.226 + 1.227 + // mTxStreamFrameSize tracks the progress of 1.228 + // transmitting a request body data frame. The data frame itself 1.229 + // is never copied into the spdy layer. 1.230 + uint32_t mTxStreamFrameSize; 1.231 + 1.232 + // Buffer for request header compression. 1.233 + nsCString mFlatHttpRequestHeaders; 1.234 + 1.235 + // Track the content-length of a request body so that we can 1.236 + // place the fin flag on the last data packet instead of waiting 1.237 + // for a stream closed indication. Relying on stream close results 1.238 + // in an extra 0-length runt packet and seems to have some interop 1.239 + // problems with the google servers. 1.240 + int64_t mRequestBodyLenRemaining; 1.241 + 1.242 + // 0 is highest.. up to 2^31 - 1 as lowest 1.243 + uint32_t mPriority; 1.244 + 1.245 + // mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow control. 1.246 + // *window are signed because the race conditions in asynchronous SETTINGS 1.247 + // messages can force them temporarily negative. 1.248 + 1.249 + // mClientReceiveWindow is how much data the server will send without getting a 1.250 + // window update 1.251 + int64_t mClientReceiveWindow; 1.252 + 1.253 + // mServerReceiveWindow is how much data the client is allowed to send without 1.254 + // getting a window update 1.255 + int64_t mServerReceiveWindow; 1.256 + 1.257 + // LocalUnacked is the number of bytes received by the client but not 1.258 + // yet reflected in a window update. Sending that update will increment 1.259 + // ClientReceiveWindow 1.260 + uint64_t mLocalUnacked; 1.261 + 1.262 + // True when sending is suspended becuase the server receive window is 1.263 + // <= 0 1.264 + bool mBlockedOnRwin; 1.265 + 1.266 + // For Progress Events 1.267 + uint64_t mTotalSent; 1.268 + uint64_t mTotalRead; 1.269 + 1.270 + // For Http2Push 1.271 + Http2PushedStream *mPushSource; 1.272 +}; 1.273 + 1.274 +} // namespace mozilla::net 1.275 +} // namespace mozilla 1.276 + 1.277 +#endif // mozilla_net_Http2Stream_h