netwerk/protocol/http/Http2Push.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

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.)

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

mercurial