netwerk/protocol/http/SpdyPush3.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 "SpdyPush3.h"
michael@0 19 #include "PSpdyPush.h"
michael@0 20 #include "SpdySession3.h"
michael@0 21 #include "nsHttpRequestHead.h"
michael@0 22
michael@0 23 namespace mozilla {
michael@0 24 namespace net {
michael@0 25
michael@0 26 //////////////////////////////////////////
michael@0 27 // SpdyPushedStream3
michael@0 28 //////////////////////////////////////////
michael@0 29
michael@0 30 SpdyPushedStream3::SpdyPushedStream3(SpdyPush3TransactionBuffer *aTransaction,
michael@0 31 SpdySession3 *aSession,
michael@0 32 SpdyStream3 *aAssociatedStream,
michael@0 33 uint32_t aID)
michael@0 34 :SpdyStream3(aTransaction, aSession,
michael@0 35 0 /* priority is only for sending, so ignore it on push */)
michael@0 36 , mConsumerStream(nullptr)
michael@0 37 , mBufferedPush(aTransaction)
michael@0 38 , mStatus(NS_OK)
michael@0 39 , mPushCompleted(false)
michael@0 40 , mDeferCleanupOnSuccess(true)
michael@0 41 {
michael@0 42 LOG3(("SpdyPushedStream3 ctor this=%p 0x%X\n", this, aID));
michael@0 43 mStreamID = aID;
michael@0 44 mBufferedPush->SetPushStream(this);
michael@0 45 mLoadGroupCI = aAssociatedStream->LoadGroupConnectionInfo();
michael@0 46 mLastRead = TimeStamp::Now();
michael@0 47 }
michael@0 48
michael@0 49 bool
michael@0 50 SpdyPushedStream3::GetPushComplete()
michael@0 51 {
michael@0 52 return mPushCompleted;
michael@0 53 }
michael@0 54
michael@0 55 nsresult
michael@0 56 SpdyPushedStream3::WriteSegments(nsAHttpSegmentWriter *writer,
michael@0 57 uint32_t count,
michael@0 58 uint32_t *countWritten)
michael@0 59 {
michael@0 60 nsresult rv = SpdyStream3::WriteSegments(writer, count, countWritten);
michael@0 61 if (NS_SUCCEEDED(rv) && *countWritten) {
michael@0 62 mLastRead = TimeStamp::Now();
michael@0 63 }
michael@0 64
michael@0 65 if (rv == NS_BASE_STREAM_CLOSED) {
michael@0 66 mPushCompleted = true;
michael@0 67 rv = NS_OK; // this is what a normal HTTP transaction would do
michael@0 68 }
michael@0 69 if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv))
michael@0 70 mStatus = rv;
michael@0 71 return rv;
michael@0 72 }
michael@0 73
michael@0 74 nsresult
michael@0 75 SpdyPushedStream3::ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *count)
michael@0 76 {
michael@0 77 // The SYN_STREAM for this has been processed, so we need to verify
michael@0 78 // that :host, :scheme, and :path MUST be present
michael@0 79 nsDependentCSubstring host, scheme, path;
michael@0 80 nsresult rv;
michael@0 81
michael@0 82 rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":host"), host);
michael@0 83 if (NS_FAILED(rv)) {
michael@0 84 LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
michael@0 85 "push without required :host\n", mSession, mStreamID));
michael@0 86 return rv;
michael@0 87 }
michael@0 88
michael@0 89 rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":scheme"), scheme);
michael@0 90 if (NS_FAILED(rv)) {
michael@0 91 LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
michael@0 92 "push without required :scheme\n", mSession, mStreamID));
michael@0 93 return rv;
michael@0 94 }
michael@0 95
michael@0 96 rv = SpdyStream3::FindHeader(NS_LITERAL_CSTRING(":path"), path);
michael@0 97 if (NS_FAILED(rv)) {
michael@0 98 LOG3(("SpdyPushedStream3::ReadSegments session=%p ID 0x%X "
michael@0 99 "push without required :host\n", mSession, mStreamID));
michael@0 100 return rv;
michael@0 101 }
michael@0 102
michael@0 103 CreatePushHashKey(nsCString(scheme), nsCString(host),
michael@0 104 mSession->Serial(), path,
michael@0 105 mOrigin, mHashKey);
michael@0 106
michael@0 107 LOG3(("SpdyPushStream3 0x%X hash key %s\n", mStreamID, mHashKey.get()));
michael@0 108
michael@0 109 // the write side of a pushed transaction just involves manipulating a little state
michael@0 110 SpdyStream3::mSentFinOnData = 1;
michael@0 111 SpdyStream3::mSynFrameComplete = 1;
michael@0 112 SpdyStream3::ChangeState(UPSTREAM_COMPLETE);
michael@0 113 *count = 0;
michael@0 114 return NS_OK;
michael@0 115 }
michael@0 116
michael@0 117 bool
michael@0 118 SpdyPushedStream3::GetHashKey(nsCString &key)
michael@0 119 {
michael@0 120 if (mHashKey.IsEmpty())
michael@0 121 return false;
michael@0 122
michael@0 123 key = mHashKey;
michael@0 124 return true;
michael@0 125 }
michael@0 126
michael@0 127 void
michael@0 128 SpdyPushedStream3::ConnectPushedStream(SpdyStream3 *stream)
michael@0 129 {
michael@0 130 mSession->ConnectPushedStream(stream);
michael@0 131 }
michael@0 132
michael@0 133 bool
michael@0 134 SpdyPushedStream3::IsOrphaned(TimeStamp now)
michael@0 135 {
michael@0 136 MOZ_ASSERT(!now.IsNull());
michael@0 137
michael@0 138 // if spdy is not transmitting, and is also not connected to a consumer
michael@0 139 // stream, and its been like that for too long then it is oprhaned
michael@0 140
michael@0 141 if (mConsumerStream)
michael@0 142 return false;
michael@0 143
michael@0 144 bool rv = ((now - mLastRead).ToSeconds() > 30.0);
michael@0 145 if (rv) {
michael@0 146 LOG3(("SpdyPushCache::IsOrphaned 0x%X IsOrphaned %3.2f\n",
michael@0 147 mStreamID, (now - mLastRead).ToSeconds()));
michael@0 148 }
michael@0 149 return rv;
michael@0 150 }
michael@0 151
michael@0 152 nsresult
michael@0 153 SpdyPushedStream3::GetBufferedData(char *buf,
michael@0 154 uint32_t count,
michael@0 155 uint32_t *countWritten)
michael@0 156 {
michael@0 157 if (NS_FAILED(mStatus))
michael@0 158 return mStatus;
michael@0 159
michael@0 160 nsresult rv = mBufferedPush->GetBufferedData(buf, count, countWritten);
michael@0 161 if (NS_FAILED(rv))
michael@0 162 return rv;
michael@0 163
michael@0 164 if (!*countWritten)
michael@0 165 rv = GetPushComplete() ? NS_BASE_STREAM_CLOSED : NS_BASE_STREAM_WOULD_BLOCK;
michael@0 166
michael@0 167 return rv;
michael@0 168 }
michael@0 169
michael@0 170 //////////////////////////////////////////
michael@0 171 // SpdyPush3TransactionBuffer
michael@0 172 // This is the nsAHttpTransction owned by the stream when the pushed
michael@0 173 // stream has not yet been matched with a pull request
michael@0 174 //////////////////////////////////////////
michael@0 175
michael@0 176 NS_IMPL_ISUPPORTS0(SpdyPush3TransactionBuffer)
michael@0 177
michael@0 178 SpdyPush3TransactionBuffer::SpdyPush3TransactionBuffer()
michael@0 179 : mStatus(NS_OK)
michael@0 180 , mRequestHead(nullptr)
michael@0 181 , mPushStream(nullptr)
michael@0 182 , mIsDone(false)
michael@0 183 , mBufferedHTTP1Size(kDefaultBufferSize)
michael@0 184 , mBufferedHTTP1Used(0)
michael@0 185 , mBufferedHTTP1Consumed(0)
michael@0 186 {
michael@0 187 mBufferedHTTP1 = new char[mBufferedHTTP1Size];
michael@0 188 }
michael@0 189
michael@0 190 SpdyPush3TransactionBuffer::~SpdyPush3TransactionBuffer()
michael@0 191 {
michael@0 192 delete mRequestHead;
michael@0 193 }
michael@0 194
michael@0 195 void
michael@0 196 SpdyPush3TransactionBuffer::SetConnection(nsAHttpConnection *conn)
michael@0 197 {
michael@0 198 }
michael@0 199
michael@0 200 nsAHttpConnection *
michael@0 201 SpdyPush3TransactionBuffer::Connection()
michael@0 202 {
michael@0 203 return nullptr;
michael@0 204 }
michael@0 205
michael@0 206 void
michael@0 207 SpdyPush3TransactionBuffer::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
michael@0 208 {
michael@0 209 *outCB = nullptr;
michael@0 210 }
michael@0 211
michael@0 212 void
michael@0 213 SpdyPush3TransactionBuffer::OnTransportStatus(nsITransport* transport,
michael@0 214 nsresult status, uint64_t progress)
michael@0 215 {
michael@0 216 }
michael@0 217
michael@0 218 bool
michael@0 219 SpdyPush3TransactionBuffer::IsDone()
michael@0 220 {
michael@0 221 return mIsDone;
michael@0 222 }
michael@0 223
michael@0 224 nsresult
michael@0 225 SpdyPush3TransactionBuffer::Status()
michael@0 226 {
michael@0 227 return mStatus;
michael@0 228 }
michael@0 229
michael@0 230 uint32_t
michael@0 231 SpdyPush3TransactionBuffer::Caps()
michael@0 232 {
michael@0 233 return 0;
michael@0 234 }
michael@0 235
michael@0 236 void
michael@0 237 SpdyPush3TransactionBuffer::SetDNSWasRefreshed()
michael@0 238 {
michael@0 239 }
michael@0 240
michael@0 241 uint64_t
michael@0 242 SpdyPush3TransactionBuffer::Available()
michael@0 243 {
michael@0 244 return mBufferedHTTP1Used - mBufferedHTTP1Consumed;
michael@0 245 }
michael@0 246
michael@0 247 nsresult
michael@0 248 SpdyPush3TransactionBuffer::ReadSegments(nsAHttpSegmentReader *reader,
michael@0 249 uint32_t count, uint32_t *countRead)
michael@0 250 {
michael@0 251 *countRead = 0;
michael@0 252 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 253 }
michael@0 254
michael@0 255 nsresult
michael@0 256 SpdyPush3TransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
michael@0 257 uint32_t count, uint32_t *countWritten)
michael@0 258 {
michael@0 259 if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
michael@0 260 SpdySession3::EnsureBuffer(mBufferedHTTP1,
michael@0 261 mBufferedHTTP1Size + kDefaultBufferSize,
michael@0 262 mBufferedHTTP1Used,
michael@0 263 mBufferedHTTP1Size);
michael@0 264 }
michael@0 265
michael@0 266 count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
michael@0 267 nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
michael@0 268 count, countWritten);
michael@0 269 if (NS_SUCCEEDED(rv)) {
michael@0 270 mBufferedHTTP1Used += *countWritten;
michael@0 271 }
michael@0 272 else if (rv == NS_BASE_STREAM_CLOSED) {
michael@0 273 mIsDone = true;
michael@0 274 }
michael@0 275
michael@0 276 if (Available()) {
michael@0 277 SpdyStream3 *consumer = mPushStream->GetConsumerStream();
michael@0 278
michael@0 279 if (consumer) {
michael@0 280 LOG3(("SpdyPush3TransactionBuffer::WriteSegments notifying connection "
michael@0 281 "consumer data available 0x%X [%u]\n",
michael@0 282 mPushStream->StreamID(), Available()));
michael@0 283 mPushStream->ConnectPushedStream(consumer);
michael@0 284 }
michael@0 285 }
michael@0 286
michael@0 287 return rv;
michael@0 288 }
michael@0 289
michael@0 290 uint32_t
michael@0 291 SpdyPush3TransactionBuffer::Http1xTransactionCount()
michael@0 292 {
michael@0 293 return 0;
michael@0 294 }
michael@0 295
michael@0 296 nsHttpRequestHead *
michael@0 297 SpdyPush3TransactionBuffer::RequestHead()
michael@0 298 {
michael@0 299 if (!mRequestHead)
michael@0 300 mRequestHead = new nsHttpRequestHead();
michael@0 301 return mRequestHead;
michael@0 302 }
michael@0 303
michael@0 304 nsresult
michael@0 305 SpdyPush3TransactionBuffer::TakeSubTransactions(
michael@0 306 nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
michael@0 307 {
michael@0 308 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 309 }
michael@0 310
michael@0 311 void
michael@0 312 SpdyPush3TransactionBuffer::SetProxyConnectFailed()
michael@0 313 {
michael@0 314 }
michael@0 315
michael@0 316 void
michael@0 317 SpdyPush3TransactionBuffer::Close(nsresult reason)
michael@0 318 {
michael@0 319 mStatus = reason;
michael@0 320 mIsDone = true;
michael@0 321 }
michael@0 322
michael@0 323 nsresult
michael@0 324 SpdyPush3TransactionBuffer::AddTransaction(nsAHttpTransaction *trans)
michael@0 325 {
michael@0 326 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 327 }
michael@0 328
michael@0 329 uint32_t
michael@0 330 SpdyPush3TransactionBuffer::PipelineDepth()
michael@0 331 {
michael@0 332 return 0;
michael@0 333 }
michael@0 334
michael@0 335 nsresult
michael@0 336 SpdyPush3TransactionBuffer::SetPipelinePosition(int32_t position)
michael@0 337 {
michael@0 338 return NS_OK;
michael@0 339 }
michael@0 340
michael@0 341 int32_t
michael@0 342 SpdyPush3TransactionBuffer::PipelinePosition()
michael@0 343 {
michael@0 344 return 1;
michael@0 345 }
michael@0 346
michael@0 347 nsresult
michael@0 348 SpdyPush3TransactionBuffer::GetBufferedData(char *buf,
michael@0 349 uint32_t count,
michael@0 350 uint32_t *countWritten)
michael@0 351 {
michael@0 352 *countWritten = std::min(count, static_cast<uint32_t>(Available()));
michael@0 353 if (*countWritten) {
michael@0 354 memcpy(buf, mBufferedHTTP1 + mBufferedHTTP1Consumed, *countWritten);
michael@0 355 mBufferedHTTP1Consumed += *countWritten;
michael@0 356 }
michael@0 357
michael@0 358 // If all the data has been consumed then reset the buffer
michael@0 359 if (mBufferedHTTP1Consumed == mBufferedHTTP1Used) {
michael@0 360 mBufferedHTTP1Consumed = 0;
michael@0 361 mBufferedHTTP1Used = 0;
michael@0 362 }
michael@0 363
michael@0 364 return NS_OK;
michael@0 365 }
michael@0 366
michael@0 367 } // namespace mozilla::net
michael@0 368 } // namespace mozilla

mercurial