netwerk/protocol/http/SpdyPush31.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.)

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

mercurial