Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // HttpLog.h should generally be included first
8 #include "HttpLog.h"
10 // Log on level :5, instead of default :4.
11 #undef LOG
12 #define LOG(args) LOG5(args)
13 #undef LOG_ENABLED
14 #define LOG_ENABLED() LOG5_ENABLED()
16 #include <algorithm>
18 #include "Http2Push.h"
20 #include "nsDependentString.h"
22 namespace mozilla {
23 namespace net {
25 //////////////////////////////////////////
26 // Http2PushedStream
27 //////////////////////////////////////////
29 Http2PushedStream::Http2PushedStream(Http2PushTransactionBuffer *aTransaction,
30 Http2Session *aSession,
31 Http2Stream *aAssociatedStream,
32 uint32_t aID)
33 :Http2Stream(aTransaction, aSession, 0)
34 , mConsumerStream(nullptr)
35 , mBufferedPush(aTransaction)
36 , mStatus(NS_OK)
37 , mPushCompleted(false)
38 , mDeferCleanupOnSuccess(true)
39 {
40 LOG3(("Http2PushedStream ctor this=%p 0x%X\n", this, aID));
41 mStreamID = aID;
42 MOZ_ASSERT(!(aID & 1)); // must be even to be a pushed stream
43 mBufferedPush->SetPushStream(this);
44 mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
45 mLastRead = TimeStamp::Now();
46 SetPriority(aAssociatedStream->Priority() + 1);
47 }
49 bool
50 Http2PushedStream::GetPushComplete()
51 {
52 return mPushCompleted;
53 }
55 nsresult
56 Http2PushedStream::WriteSegments(nsAHttpSegmentWriter *writer,
57 uint32_t count, uint32_t *countWritten)
58 {
59 nsresult rv = Http2Stream::WriteSegments(writer, count, countWritten);
60 if (NS_SUCCEEDED(rv) && *countWritten) {
61 mLastRead = TimeStamp::Now();
62 }
64 if (rv == NS_BASE_STREAM_CLOSED) {
65 mPushCompleted = true;
66 rv = NS_OK; // this is what a normal HTTP transaction would do
67 }
68 if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv))
69 mStatus = rv;
70 return rv;
71 }
73 nsresult
74 Http2PushedStream::ReadSegments(nsAHttpSegmentReader *,
75 uint32_t, uint32_t *count)
76 {
77 // The request headers for this has been processed, so we need to verify
78 // that :authority, :scheme, and :path MUST be present. :method MUST NOT be
79 // present
80 CreatePushHashKey(mHeaderScheme, mHeaderHost,
81 mSession->Serial(), mHeaderPath,
82 mOrigin, mHashKey);
84 LOG3(("Http2PushStream 0x%X hash key %s\n", mStreamID, mHashKey.get()));
86 // the write side of a pushed transaction just involves manipulating a little state
87 SetSentFin(true);
88 Http2Stream::mAllHeadersSent = 1;
89 Http2Stream::ChangeState(UPSTREAM_COMPLETE);
90 *count = 0;
91 return NS_OK;
92 }
94 bool
95 Http2PushedStream::GetHashKey(nsCString &key)
96 {
97 if (mHashKey.IsEmpty())
98 return false;
100 key = mHashKey;
101 return true;
102 }
104 void
105 Http2PushedStream::ConnectPushedStream(Http2Stream *stream)
106 {
107 mSession->ConnectPushedStream(stream);
108 }
110 bool
111 Http2PushedStream::IsOrphaned(TimeStamp now)
112 {
113 MOZ_ASSERT(!now.IsNull());
115 // if session is not transmitting, and is also not connected to a consumer
116 // stream, and its been like that for too long then it is oprhaned
118 if (mConsumerStream)
119 return false;
121 bool rv = ((now - mLastRead).ToSeconds() > 30.0);
122 if (rv) {
123 LOG3(("Http2PushedStream:IsOrphaned 0x%X IsOrphaned %3.2f\n",
124 mStreamID, (now - mLastRead).ToSeconds()));
125 }
126 return rv;
127 }
129 nsresult
130 Http2PushedStream::GetBufferedData(char *buf,
131 uint32_t count, uint32_t *countWritten)
132 {
133 if (NS_FAILED(mStatus))
134 return mStatus;
136 nsresult rv = mBufferedPush->GetBufferedData(buf, count, countWritten);
137 if (NS_FAILED(rv))
138 return rv;
140 if (!*countWritten)
141 rv = GetPushComplete() ? NS_BASE_STREAM_CLOSED : NS_BASE_STREAM_WOULD_BLOCK;
143 return rv;
144 }
146 //////////////////////////////////////////
147 // Http2PushTransactionBuffer
148 // This is the nsAHttpTransction owned by the stream when the pushed
149 // stream has not yet been matched with a pull request
150 //////////////////////////////////////////
152 NS_IMPL_ISUPPORTS0(Http2PushTransactionBuffer)
154 Http2PushTransactionBuffer::Http2PushTransactionBuffer()
155 : mStatus(NS_OK)
156 , mRequestHead(nullptr)
157 , mPushStream(nullptr)
158 , mIsDone(false)
159 , mBufferedHTTP1Size(kDefaultBufferSize)
160 , mBufferedHTTP1Used(0)
161 , mBufferedHTTP1Consumed(0)
162 {
163 mBufferedHTTP1 = new char[mBufferedHTTP1Size];
164 }
166 Http2PushTransactionBuffer::~Http2PushTransactionBuffer()
167 {
168 delete mRequestHead;
169 }
171 void
172 Http2PushTransactionBuffer::SetConnection(nsAHttpConnection *conn)
173 {
174 }
176 nsAHttpConnection *
177 Http2PushTransactionBuffer::Connection()
178 {
179 return nullptr;
180 }
182 void
183 Http2PushTransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
184 {
185 *outCB = nullptr;
186 }
188 void
189 Http2PushTransactionBuffer::OnTransportStatus(nsITransport* transport,
190 nsresult status, uint64_t progress)
191 {
192 }
194 bool
195 Http2PushTransactionBuffer::IsDone()
196 {
197 return mIsDone;
198 }
200 nsresult
201 Http2PushTransactionBuffer::Status()
202 {
203 return mStatus;
204 }
206 uint32_t
207 Http2PushTransactionBuffer::Caps()
208 {
209 return 0;
210 }
212 void
213 Http2PushTransactionBuffer::SetDNSWasRefreshed()
214 {
215 }
217 uint64_t
218 Http2PushTransactionBuffer::Available()
219 {
220 return mBufferedHTTP1Used - mBufferedHTTP1Consumed;
221 }
223 nsresult
224 Http2PushTransactionBuffer::ReadSegments(nsAHttpSegmentReader *reader,
225 uint32_t count, uint32_t *countRead)
226 {
227 *countRead = 0;
228 return NS_ERROR_NOT_IMPLEMENTED;
229 }
231 nsresult
232 Http2PushTransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
233 uint32_t count, uint32_t *countWritten)
234 {
235 if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
236 Http2Session::EnsureBuffer(mBufferedHTTP1,
237 mBufferedHTTP1Size + kDefaultBufferSize,
238 mBufferedHTTP1Used,
239 mBufferedHTTP1Size);
240 }
242 count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
243 nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
244 count, countWritten);
245 if (NS_SUCCEEDED(rv)) {
246 mBufferedHTTP1Used += *countWritten;
247 }
248 else if (rv == NS_BASE_STREAM_CLOSED) {
249 mIsDone = true;
250 }
252 if (Available()) {
253 Http2Stream *consumer = mPushStream->GetConsumerStream();
255 if (consumer) {
256 LOG3(("Http2PushTransactionBuffer::WriteSegments notifying connection "
257 "consumer data available 0x%X [%u]\n",
258 mPushStream->StreamID(), Available()));
259 mPushStream->ConnectPushedStream(consumer);
260 }
261 }
263 return rv;
264 }
266 uint32_t
267 Http2PushTransactionBuffer::Http1xTransactionCount()
268 {
269 return 0;
270 }
272 nsHttpRequestHead *
273 Http2PushTransactionBuffer::RequestHead()
274 {
275 if (!mRequestHead)
276 mRequestHead = new nsHttpRequestHead();
277 return mRequestHead;
278 }
280 nsresult
281 Http2PushTransactionBuffer::TakeSubTransactions(
282 nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
283 {
284 return NS_ERROR_NOT_IMPLEMENTED;
285 }
287 void
288 Http2PushTransactionBuffer::SetProxyConnectFailed()
289 {
290 }
292 void
293 Http2PushTransactionBuffer::Close(nsresult reason)
294 {
295 mStatus = reason;
296 mIsDone = true;
297 }
299 nsresult
300 Http2PushTransactionBuffer::AddTransaction(nsAHttpTransaction *trans)
301 {
302 return NS_ERROR_NOT_IMPLEMENTED;
303 }
305 uint32_t
306 Http2PushTransactionBuffer::PipelineDepth()
307 {
308 return 0;
309 }
311 nsresult
312 Http2PushTransactionBuffer::SetPipelinePosition(int32_t position)
313 {
314 return NS_OK;
315 }
317 int32_t
318 Http2PushTransactionBuffer::PipelinePosition()
319 {
320 return 1;
321 }
323 nsresult
324 Http2PushTransactionBuffer::GetBufferedData(char *buf,
325 uint32_t count,
326 uint32_t *countWritten)
327 {
328 *countWritten = std::min(count, static_cast<uint32_t>(Available()));
329 if (*countWritten) {
330 memcpy(buf, mBufferedHTTP1 + mBufferedHTTP1Consumed, *countWritten);
331 mBufferedHTTP1Consumed += *countWritten;
332 }
334 // If all the data has been consumed then reset the buffer
335 if (mBufferedHTTP1Consumed == mBufferedHTTP1Used) {
336 mBufferedHTTP1Consumed = 0;
337 mBufferedHTTP1Used = 0;
338 }
340 return NS_OK;
341 }
343 } // namespace mozilla::net
344 } // namespace mozilla