1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set sw=2 ts=8 et tw=80 : */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2011
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Patrick McManus <mcmanus@ducksong.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef mozilla_net_SpdyStream_h
41 : #define mozilla_net_SpdyStream_h
42 :
43 : #include "nsAHttpTransaction.h"
44 :
45 : namespace mozilla { namespace net {
46 :
47 : class SpdyStream : public nsAHttpSegmentReader
48 : , public nsAHttpSegmentWriter
49 : {
50 : public:
51 : NS_DECL_NSAHTTPSEGMENTREADER
52 : NS_DECL_NSAHTTPSEGMENTWRITER
53 :
54 : SpdyStream(nsAHttpTransaction *,
55 : SpdySession *, nsISocketTransport *,
56 : PRUint32, z_stream *, PRInt32);
57 :
58 0 : PRUint32 StreamID() { return mStreamID; }
59 :
60 : nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *);
61 : nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *);
62 :
63 0 : bool RequestBlockedOnRead()
64 : {
65 0 : return static_cast<bool>(mRequestBlockedOnRead);
66 : }
67 :
68 : // returns false if called more than once
69 0 : bool GetFullyOpen() {return mFullyOpen;}
70 0 : void SetFullyOpen()
71 : {
72 0 : NS_ABORT_IF_FALSE(!mFullyOpen, "SetFullyOpen already open");
73 0 : mFullyOpen = 1;
74 0 : }
75 :
76 0 : nsAHttpTransaction *Transaction()
77 : {
78 0 : return mTransaction;
79 : }
80 :
81 : void Close(nsresult reason);
82 :
83 0 : void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; }
84 0 : bool RecvdFin() { return mRecvdFin; }
85 :
86 : void UpdateTransportSendEvents(PRUint32 count);
87 : void UpdateTransportReadEvents(PRUint32 count);
88 :
89 : // The zlib header compression dictionary defined by SPDY,
90 : // and hooks to the mozilla allocator for zlib to use.
91 : static const char *kDictionary;
92 : static void *zlib_allocator(void *, uInt, uInt);
93 : static void zlib_destructor(void *, void *);
94 :
95 : private:
96 :
97 : // a SpdyStream object is only destroyed by being removed from the
98 : // SpdySession mStreamTransactionHash - make the dtor private to
99 : // just the AutoPtr implementation needed for that hash.
100 : friend class nsAutoPtr<SpdyStream>;
101 : ~SpdyStream();
102 :
103 : enum stateType {
104 : GENERATING_SYN_STREAM,
105 : SENDING_SYN_STREAM,
106 : GENERATING_REQUEST_BODY,
107 : SENDING_REQUEST_BODY,
108 : SENDING_FIN_STREAM,
109 : UPSTREAM_COMPLETE
110 : };
111 :
112 : static PLDHashOperator hdrHashEnumerate(const nsACString &,
113 : nsAutoPtr<nsCString> &,
114 : void *);
115 :
116 : void ChangeState(enum stateType);
117 : nsresult ParseHttpRequestHeaders(const char *, PRUint32, PRUint32 *);
118 : nsresult TransmitFrame(const char *, PRUint32 *);
119 : void GenerateDataFrameHeader(PRUint32, bool);
120 :
121 : void CompressToFrame(const nsACString &);
122 : void CompressToFrame(const nsACString *);
123 : void CompressToFrame(const char *, PRUint32);
124 : void CompressToFrame(PRUint16);
125 : void CompressFlushFrame();
126 : void ExecuteCompress(PRUint32);
127 :
128 : // Each stream goes from syn_stream to upstream_complete, perhaps
129 : // looping on multiple instances of generating_request_body and
130 : // sending_request_body for each SPDY chunk in the upload.
131 : enum stateType mUpstreamState;
132 :
133 : // The underlying HTTP transaction. This pointer is used as the key
134 : // in the SpdySession mStreamTransactionHash so it is important to
135 : // keep a reference to it as long as this stream is a member of that hash.
136 : // (i.e. don't change it or release it after it is set in the ctor).
137 : nsRefPtr<nsAHttpTransaction> mTransaction;
138 :
139 : // The session that this stream is a subset of
140 : SpdySession *mSession;
141 :
142 : // The underlying socket transport object is needed to propogate some events
143 : nsISocketTransport *mSocketTransport;
144 :
145 : // These are temporary state variables to hold the argument to
146 : // Read/WriteSegments so it can be accessed by On(read/write)segment
147 : // further up the stack.
148 : nsAHttpSegmentReader *mSegmentReader;
149 : nsAHttpSegmentWriter *mSegmentWriter;
150 :
151 : // The 24 bit SPDY stream ID
152 : PRUint32 mStreamID;
153 :
154 : // The quanta upstream data frames are chopped into
155 : PRUint32 mChunkSize;
156 :
157 : // Flag is set when all http request headers have been read
158 : PRUint32 mSynFrameComplete : 1;
159 :
160 : // Flag is set when the HTTP processor has more data to send
161 : // but has blocked in doing so.
162 : PRUint32 mRequestBlockedOnRead : 1;
163 :
164 : // Flag is set when a FIN has been placed on a data or syn packet
165 : // (i.e after the client has closed)
166 : PRUint32 mSentFinOnData : 1;
167 :
168 : // Flag is set after the response frame bearing the fin bit has
169 : // been processed. (i.e. after the server has closed).
170 : PRUint32 mRecvdFin : 1;
171 :
172 : // Flag is set after syn reply received
173 : PRUint32 mFullyOpen : 1;
174 :
175 : // Flag is set after the WAITING_FOR Transport event has been generated
176 : PRUint32 mSentWaitingFor : 1;
177 :
178 : // The InlineFrame and associated data is used for composing control
179 : // frames and data frame headers.
180 : nsAutoArrayPtr<char> mTxInlineFrame;
181 : PRUint32 mTxInlineFrameSize;
182 : PRUint32 mTxInlineFrameUsed;
183 :
184 : // mTxStreamFrameSize tracks the progress of
185 : // transmitting a request body data frame. The data frame itself
186 : // is never copied into the spdy layer.
187 : PRUint32 mTxStreamFrameSize;
188 :
189 : // Compression context and buffer for request header compression.
190 : // This is a copy of SpdySession::mUpstreamZlib because it needs
191 : // to remain the same in all streams of a session.
192 : z_stream *mZlib;
193 : nsCString mFlatHttpRequestHeaders;
194 :
195 : // Track the content-length of a request body so that we can
196 : // place the fin flag on the last data packet instead of waiting
197 : // for a stream closed indication. Relying on stream close results
198 : // in an extra 0-length runt packet and seems to have some interop
199 : // problems with the google servers.
200 : PRInt64 mRequestBodyLenRemaining;
201 :
202 : // based on nsISupportsPriority definitions
203 : PRInt32 mPriority;
204 :
205 : // For Progress Events
206 : PRUint64 mTotalSent;
207 : PRUint64 mTotalRead;
208 : };
209 :
210 : }} // namespace mozilla::net
211 :
212 : #endif // mozilla_net_SpdyStream_h
|