LCOV - code coverage report
Current view: top level - netwerk/protocol/http - nsHttpTransaction.h (source / functions) Hit Total Coverage
Test: output.info Lines: 15 39 38.5 %
Date: 2017-07-14 16:53:18 Functions: 14 30 46.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef nsHttpTransaction_h__
       7             : #define nsHttpTransaction_h__
       8             : 
       9             : #include "nsHttp.h"
      10             : #include "nsAHttpTransaction.h"
      11             : #include "nsAHttpConnection.h"
      12             : #include "EventTokenBucket.h"
      13             : #include "nsCOMPtr.h"
      14             : #include "nsThreadUtils.h"
      15             : #include "nsIInterfaceRequestor.h"
      16             : #include "TimingStruct.h"
      17             : #include "Http2Push.h"
      18             : #include "mozilla/net/DNS.h"
      19             : #include "ARefBase.h"
      20             : #include "AlternateServices.h"
      21             : 
      22             : //-----------------------------------------------------------------------------
      23             : 
      24             : class nsIHttpActivityObserver;
      25             : class nsIEventTarget;
      26             : class nsIInputStream;
      27             : class nsIOutputStream;
      28             : class nsIRequestContext;
      29             : 
      30             : namespace mozilla { namespace net {
      31             : 
      32             : class nsHttpChunkedDecoder;
      33             : class nsHttpRequestHead;
      34             : class nsHttpResponseHead;
      35             : 
      36             : //-----------------------------------------------------------------------------
      37             : // nsHttpTransaction represents a single HTTP transaction.  It is thread-safe,
      38             : // intended to run on the socket thread.
      39             : //-----------------------------------------------------------------------------
      40             : 
      41             : class nsHttpTransaction final : public nsAHttpTransaction
      42             :                               , public ATokenBucketEvent
      43             :                               , public nsIInputStreamCallback
      44             :                               , public nsIOutputStreamCallback
      45             :                               , public ARefBase
      46             : {
      47             : public:
      48             :     NS_DECL_THREADSAFE_ISUPPORTS
      49             :     NS_DECL_NSAHTTPTRANSACTION
      50             :     NS_DECL_NSIINPUTSTREAMCALLBACK
      51             :     NS_DECL_NSIOUTPUTSTREAMCALLBACK
      52             : 
      53             :     nsHttpTransaction();
      54             : 
      55             :     //
      56             :     // called to initialize the transaction
      57             :     //
      58             :     // @param caps
      59             :     //        the transaction capabilities (see nsHttp.h)
      60             :     // @param connInfo
      61             :     //        the connection type for this transaction.
      62             :     // @param reqHeaders
      63             :     //        the request header struct
      64             :     // @param reqBody
      65             :     //        the request body (POST or PUT data stream)
      66             :     // @param reqBodyIncludesHeaders
      67             :     //        fun stuff to support NPAPI plugins.
      68             :     // @param target
      69             :     //        the dispatch target were notifications should be sent.
      70             :     // @param callbacks
      71             :     //        the notification callbacks to be given to PSM.
      72             :     // @param topLevelOuterContentWindowId
      73             :     //        indicate the top level outer content window in which
      74             :     //        this transaction is being loaded.
      75             :     // @param responseBody
      76             :     //        the input stream that will contain the response data.  async
      77             :     //        wait on this input stream for data.  on first notification,
      78             :     //        headers should be available (check transaction status).
      79             :     //
      80             :     MOZ_MUST_USE nsresult Init(uint32_t               caps,
      81             :                                nsHttpConnectionInfo  *connInfo,
      82             :                                nsHttpRequestHead     *reqHeaders,
      83             :                                nsIInputStream        *reqBody,
      84             :                                uint64_t               reqContentLength,
      85             :                                bool                   reqBodyIncludesHeaders,
      86             :                                nsIEventTarget        *consumerTarget,
      87             :                                nsIInterfaceRequestor *callbacks,
      88             :                                nsITransportEventSink *eventsink,
      89             :                                uint64_t               topLevelOuterContentWindowId,
      90             :                                nsIAsyncInputStream  **responseBody);
      91             : 
      92             :     void OnActivated(bool h2) override;
      93             : 
      94             :     // attributes
      95             :     nsHttpResponseHead    *ResponseHead()   { return mHaveAllHeaders ? mResponseHead : nullptr; }
      96           3 :     nsISupports           *SecurityInfo()   { return mSecurityInfo; }
      97             : 
      98             :     nsIEventTarget        *ConsumerTarget() { return mConsumerTarget; }
      99           0 :     nsISupports           *HttpChannel()    { return mChannel; }
     100             : 
     101             :     void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks);
     102             : 
     103             :     // Called to take ownership of the response headers; the transaction
     104             :     // will drop any reference to the response headers after this call.
     105             :     nsHttpResponseHead *TakeResponseHead();
     106             : 
     107             :     // Provides a thread safe reference of the connection
     108             :     // nsHttpTransaction::Connection should only be used on the socket thread
     109             :     already_AddRefed<nsAHttpConnection> GetConnectionReference();
     110             : 
     111             :     // Called to set/find out if the transaction generated a complete response.
     112           3 :     bool ResponseIsComplete() { return mResponseIsComplete; }
     113           0 :     void SetResponseIsComplete() { mResponseIsComplete = true; }
     114             : 
     115           6 :     bool      ProxyConnectFailed() { return mProxyConnectFailed; }
     116             : 
     117           0 :     void EnableKeepAlive() { mCaps |= NS_HTTP_ALLOW_KEEPALIVE; }
     118           0 :     void MakeSticky() { mCaps |= NS_HTTP_STICKY_CONNECTION; }
     119             : 
     120             :     // SetPriority() may only be used by the connection manager.
     121           3 :     void    SetPriority(int32_t priority) { mPriority = priority; }
     122           3 :     int32_t    Priority()                 { return mPriority; }
     123             : 
     124             :     void PrintDiagnostics(nsCString &log);
     125             : 
     126             :     // Sets mPendingTime to the current time stamp or to a null time stamp (if now is false)
     127           6 :     void SetPendingTime(bool now = true) { mPendingTime = now ? TimeStamp::Now() : TimeStamp(); }
     128           6 :     const TimeStamp GetPendingTime() { return mPendingTime; }
     129             : 
     130             :     // overload of nsAHttpTransaction::RequestContext()
     131           3 :     nsIRequestContext *RequestContext() override { return mRequestContext.get(); }
     132             :     void SetRequestContext(nsIRequestContext *aRequestContext);
     133             :     void DispatchedAsBlocking();
     134             :     void RemoveDispatchedAsBlocking();
     135             : 
     136           0 :     nsHttpTransaction *QueryHttpTransaction() override { return this; }
     137             : 
     138           3 :     Http2PushedStream *GetPushedStream() { return mPushedStream; }
     139           0 :     Http2PushedStream *TakePushedStream()
     140             :     {
     141           0 :         Http2PushedStream *r = mPushedStream;
     142           0 :         mPushedStream = nullptr;
     143           0 :         return r;
     144             :     }
     145           0 :     void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
     146           0 :     uint32_t InitialRwin() const { return mInitialRwin; };
     147             :     bool ChannelPipeFull() { return mWaitingOnPipeOut; }
     148             : 
     149             :     // Locked methods to get and set timing info
     150             :     const TimingStruct Timings();
     151             :     void SetDomainLookupStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     152             :     void SetDomainLookupEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     153             :     void SetConnectStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     154             :     void SetConnectEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     155             :     void SetRequestStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     156             :     void SetResponseStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     157             :     void SetResponseEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
     158             : 
     159             :     mozilla::TimeStamp GetDomainLookupStart();
     160             :     mozilla::TimeStamp GetDomainLookupEnd();
     161             :     mozilla::TimeStamp GetConnectStart();
     162             :     mozilla::TimeStamp GetConnectEnd();
     163             :     mozilla::TimeStamp GetRequestStart();
     164             :     mozilla::TimeStamp GetResponseStart();
     165             :     mozilla::TimeStamp GetResponseEnd();
     166             : 
     167           3 :     int64_t GetTransferSize() { return mTransferSize; }
     168             : 
     169             :     MOZ_MUST_USE bool Do0RTT() override;
     170             :     MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */) override;
     171             : 
     172             :     // After Finish0RTT early data may have failed but the caller did not request
     173             :     // restart - this indicates that state for dev tools
     174             :     void Refused0RTT();
     175             : 
     176             :     MOZ_MUST_USE bool CanDo0RTT() override;
     177             :     MOZ_MUST_USE nsresult RestartOnFastOpenError() override;
     178             : 
     179          19 :     uint64_t TopLevelOuterContentWindowId() override
     180             :     {
     181          19 :         return mTopLevelOuterContentWindowId;
     182             :     }
     183             : 
     184             :     void SetFastOpenStatus(uint8_t aStatus) override;
     185             : private:
     186             :     friend class DeleteHttpTransaction;
     187             :     virtual ~nsHttpTransaction();
     188             : 
     189             :     MOZ_MUST_USE nsresult Restart();
     190             :     char    *LocateHttpStart(char *buf, uint32_t len,
     191             :                              bool aAllowPartialMatch);
     192             :     MOZ_MUST_USE nsresult ParseLine(nsACString &line);
     193             :     MOZ_MUST_USE nsresult ParseLineSegment(char *seg, uint32_t len);
     194             :     MOZ_MUST_USE nsresult ParseHead(char *, uint32_t count,
     195             :                                     uint32_t *countRead);
     196             :     MOZ_MUST_USE nsresult HandleContentStart();
     197             :     MOZ_MUST_USE nsresult HandleContent(char *, uint32_t count,
     198             :                                         uint32_t *contentRead,
     199             :                                         uint32_t *contentRemaining);
     200             :     MOZ_MUST_USE nsresult ProcessData(char *, uint32_t, uint32_t *);
     201             :     void     DeleteSelfOnConsumerThread();
     202             :     void     ReleaseBlockingTransaction();
     203             : 
     204             :     static MOZ_MUST_USE nsresult ReadRequestSegment(nsIInputStream *, void *,
     205             :                                                     const char *, uint32_t,
     206             :                                                     uint32_t, uint32_t *);
     207             :     static MOZ_MUST_USE nsresult WritePipeSegment(nsIOutputStream *, void *,
     208             :                                                   char *, uint32_t, uint32_t,
     209             :                                                   uint32_t *);
     210             : 
     211          47 :     bool TimingEnabled() const { return mCaps & NS_HTTP_TIMING_ENABLED; }
     212             : 
     213             :     bool ResponseTimeoutEnabled() const final;
     214             : 
     215             :     void DisableSpdy() override;
     216           0 :     void ReuseConnectionOnRestartOK(bool reuseOk) override { mReuseOnRestart = reuseOk; }
     217             : 
     218             :     // Called right after we parsed the response head.  Checks for connection based
     219             :     // authentication schemes in reponse headers for WWW and Proxy authentication.
     220             :     // If such is found in any of them, NS_HTTP_STICKY_CONNECTION is set in mCaps.
     221             :     // We need the sticky flag be set early to keep the connection from very start
     222             :     // of the authentication process.
     223             :     void CheckForStickyAuthScheme();
     224             :     void CheckForStickyAuthSchemeAt(nsHttpAtom const& header);
     225             : 
     226             :     // Called from WriteSegments.  Checks for conditions whether to throttle reading
     227             :     // the content.  When this returns true, WriteSegments returns WOULD_BLOCK.
     228             :     bool ShouldStopReading();
     229             : 
     230             : private:
     231           0 :     class UpdateSecurityCallbacks : public Runnable
     232             :     {
     233             :       public:
     234           0 :         UpdateSecurityCallbacks(nsHttpTransaction* aTrans,
     235             :                                 nsIInterfaceRequestor* aCallbacks)
     236           0 :           : Runnable("net::nsHttpTransaction::UpdateSecurityCallbacks")
     237             :           , mTrans(aTrans)
     238           0 :           , mCallbacks(aCallbacks)
     239             :         {
     240           0 :         }
     241             : 
     242           0 :         NS_IMETHOD Run() override
     243             :         {
     244           0 :             if (mTrans->mConnection)
     245           0 :                 mTrans->mConnection->SetSecurityCallbacks(mCallbacks);
     246           0 :             return NS_OK;
     247             :         }
     248             :       private:
     249             :         RefPtr<nsHttpTransaction> mTrans;
     250             :         nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
     251             :     };
     252             : 
     253             :     Mutex mLock;
     254             : 
     255             :     nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
     256             :     nsCOMPtr<nsITransportEventSink> mTransportSink;
     257             :     nsCOMPtr<nsIEventTarget>        mConsumerTarget;
     258             :     nsCOMPtr<nsISupports>           mSecurityInfo;
     259             :     nsCOMPtr<nsIAsyncInputStream>   mPipeIn;
     260             :     nsCOMPtr<nsIAsyncOutputStream>  mPipeOut;
     261             :     nsCOMPtr<nsIRequestContext>     mRequestContext;
     262             : 
     263             :     nsCOMPtr<nsISupports>             mChannel;
     264             :     nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
     265             : 
     266             :     nsCString                       mReqHeaderBuf;    // flattened request headers
     267             :     nsCOMPtr<nsIInputStream>        mRequestStream;
     268             :     int64_t                         mRequestSize;
     269             : 
     270             :     RefPtr<nsAHttpConnection>     mConnection;
     271             :     RefPtr<nsHttpConnectionInfo>  mConnInfo;
     272             :     nsHttpRequestHead              *mRequestHead;     // weak ref
     273             :     nsHttpResponseHead             *mResponseHead;    // owning pointer
     274             : 
     275             :     nsAHttpSegmentReader           *mReader;
     276             :     nsAHttpSegmentWriter           *mWriter;
     277             : 
     278             :     nsCString                       mLineBuf;         // may contain a partial line
     279             : 
     280             :     int64_t                         mContentLength;   // equals -1 if unknown
     281             :     int64_t                         mContentRead;     // count of consumed content bytes
     282             :     Atomic<int64_t, ReleaseAcquire> mTransferSize; // count of received bytes
     283             : 
     284             :     // After a 304/204 or other "no-content" style response we will skip over
     285             :     // up to MAX_INVALID_RESPONSE_BODY_SZ bytes when looking for the next
     286             :     // response header to deal with servers that actually sent a response
     287             :     // body where they should not have. This member tracks how many bytes have
     288             :     // so far been skipped.
     289             :     uint32_t                        mInvalidResponseBytesRead;
     290             : 
     291             :     Http2PushedStream               *mPushedStream;
     292             :     uint32_t                        mInitialRwin;
     293             : 
     294             :     nsHttpChunkedDecoder            *mChunkedDecoder;
     295             : 
     296             :     TimingStruct                    mTimings;
     297             : 
     298             :     nsresult                        mStatus;
     299             : 
     300             :     int16_t                         mPriority;
     301             : 
     302             :     uint16_t                        mRestartCount;        // the number of times this transaction has been restarted
     303             :     uint32_t                        mCaps;
     304             : 
     305             :     nsHttpVersion                   mHttpVersion;
     306             :     uint16_t                        mHttpResponseCode;
     307             : 
     308             :     uint32_t                        mCurrentHttpResponseHeaderSize;
     309             : 
     310             :     // mCapsToClear holds flags that should be cleared in mCaps, e.g. unset
     311             :     // NS_HTTP_REFRESH_DNS when DNS refresh request has completed to avoid
     312             :     // redundant requests on the network. The member itself is atomic, but
     313             :     // access to it from the networking thread may happen either before or
     314             :     // after the main thread modifies it. To deal with raciness, only unsetting
     315             :     // bitfields should be allowed: 'lost races' will thus err on the
     316             :     // conservative side, e.g. by going ahead with a 2nd DNS refresh.
     317             :     Atomic<uint32_t>                mCapsToClear;
     318             :     Atomic<bool, ReleaseAcquire>    mResponseIsComplete;
     319             : 
     320             :     // True iff WriteSegments was called while this transaction should be throttled (stop reading)
     321             :     // Used to resume read on unblock of reading.  Conn manager is responsible for calling back
     322             :     // to resume reading.
     323             :     bool                            mReadingStopped;
     324             : 
     325             :     // state flags, all logically boolean, but not packed together into a
     326             :     // bitfield so as to avoid bitfield-induced races.  See bug 560579.
     327             :     bool                            mClosed;
     328             :     bool                            mConnected;
     329             :     bool                            mActivated;
     330             :     bool                            mActivatedAsH2;
     331             :     bool                            mHaveStatusLine;
     332             :     bool                            mHaveAllHeaders;
     333             :     bool                            mTransactionDone;
     334             :     bool                            mDidContentStart;
     335             :     bool                            mNoContent; // expecting an empty entity body
     336             :     bool                            mSentData;
     337             :     bool                            mReceivedData;
     338             :     bool                            mStatusEventPending;
     339             :     bool                            mHasRequestBody;
     340             :     bool                            mProxyConnectFailed;
     341             :     bool                            mHttpResponseMatched;
     342             :     bool                            mPreserveStream;
     343             :     bool                            mDispatchedAsBlocking;
     344             :     bool                            mResponseTimeoutEnabled;
     345             :     bool                            mForceRestart;
     346             :     bool                            mReuseOnRestart;
     347             :     bool                            mContentDecoding;
     348             :     bool                            mContentDecodingCheck;
     349             :     bool                            mDeferredSendProgress;
     350             :     bool                            mWaitingOnPipeOut;
     351             : 
     352             :     // mClosed           := transaction has been explicitly closed
     353             :     // mTransactionDone  := transaction ran to completion or was interrupted
     354             :     // mResponseComplete := transaction ran to completion
     355             : 
     356             :     // For Restart-In-Progress Functionality
     357             :     bool                            mReportedStart;
     358             :     bool                            mReportedResponseHeader;
     359             : 
     360             :     // protected by nsHttp::GetLock()
     361             :     nsHttpResponseHead             *mForTakeResponseHead;
     362             :     bool                            mResponseHeadTaken;
     363             : 
     364             :     // The time when the transaction was submitted to the Connection Manager
     365             :     TimeStamp                       mPendingTime;
     366             : 
     367             :     uint64_t                        mTopLevelOuterContentWindowId;
     368             : 
     369             : // For Rate Pacing via an EventTokenBucket
     370             : public:
     371             :     // called by the connection manager to run this transaction through the
     372             :     // token bucket. If the token bucket admits the transaction immediately it
     373             :     // returns true. The function is called repeatedly until it returns true.
     374             :     bool TryToRunPacedRequest();
     375             : 
     376             :     // ATokenBucketEvent pure virtual implementation. Called by the token bucket
     377             :     // when the transaction is ready to run. If this happens asynchrounously to
     378             :     // token bucket submission the transaction just posts an event that causes
     379             :     // the pending transaction queue to be rerun (and TryToRunPacedRequest() to
     380             :     // be run again.
     381             :     void OnTokenBucketAdmitted() override; // ATokenBucketEvent
     382             : 
     383             :     // CancelPacing() can be used to tell the token bucket to remove this
     384             :     // transaction from the list of pending transactions. This is used when a
     385             :     // transaction is believed to be HTTP/1 (and thus subject to rate pacing)
     386             :     // but later can be dispatched via spdy (not subject to rate pacing).
     387             :     void CancelPacing(nsresult reason);
     388             : 
     389             :     // Called by the connetion manager on the socket thread when reading for this
     390             :     // previously throttled transaction has to be resumed.
     391             :     void ResumeReading();
     392             : 
     393             : private:
     394             :     bool mSubmittedRatePacing;
     395             :     bool mPassedRatePacing;
     396             :     bool mSynchronousRatePaceRequest;
     397             :     nsCOMPtr<nsICancelable> mTokenBucketCancel;
     398             : public:
     399             :     void     SetClassOfService(uint32_t cos);
     400           0 :     uint32_t ClassOfService() { return mClassOfService; }
     401             : private:
     402             :     uint32_t mClassOfService;
     403             : 
     404             : public:
     405             :     // setting TunnelProvider to non-null means the transaction should only
     406             :     // be dispatched on a specific ConnectionInfo Hash Key (as opposed to a
     407             :     // generic wild card one). That means in the specific case of carrying this
     408             :     // transaction on an HTTP/2 tunnel it will only be dispatched onto an
     409             :     // existing tunnel instead of triggering creation of a new one.
     410             :     // The tunnel provider is used for ASpdySession::MaybeReTunnel() checks.
     411             : 
     412           0 :     void SetTunnelProvider(ASpdySession *provider) { mTunnelProvider = provider; }
     413           6 :     ASpdySession *TunnelProvider() { return mTunnelProvider; }
     414           0 :     nsIInterfaceRequestor *SecurityCallbacks() { return mCallbacks; }
     415             : 
     416             : private:
     417             :     RefPtr<ASpdySession> mTunnelProvider;
     418             : 
     419             : public:
     420           3 :     void SetTransactionObserver(TransactionObserver *arg) { mTransactionObserver = arg; }
     421             : private:
     422             :     RefPtr<TransactionObserver> mTransactionObserver;
     423             : public:
     424             :     void GetNetworkAddresses(NetAddr &self, NetAddr &peer);
     425             : 
     426             : private:
     427             :     NetAddr                         mSelfAddr;
     428             :     NetAddr                         mPeerAddr;
     429             : 
     430             :     bool                            m0RTTInProgress;
     431             :     enum
     432             :     {
     433             :         EARLY_NONE,
     434             :         EARLY_SENT,
     435             :         EARLY_ACCEPTED
     436             :     } mEarlyDataDisposition;
     437             : 
     438             :     uint8_t mFastOpenStatus;
     439             : };
     440             : 
     441             : } // namespace net
     442             : } // namespace mozilla
     443             : 
     444             : #endif // nsHttpTransaction_h__

Generated by: LCOV version 1.13