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

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

mercurial