LCOV - code coverage report
Current view: directory - netwerk/protocol/http - nsHttpConnectionMgr.h (source / functions) Found Hit Coverage
Test: app.info Lines: 17 17 100.0 %
Date: 2012-06-02 Functions: 7 7 100.0 %

       1                 : /* vim:set ts=4 sw=4 sts=4 et cin: */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Darin Fisher <darin@netscape.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #ifndef nsHttpConnectionMgr_h__
      40                 : #define nsHttpConnectionMgr_h__
      41                 : 
      42                 : #include "nsHttpConnectionInfo.h"
      43                 : #include "nsHttpConnection.h"
      44                 : #include "nsHttpTransaction.h"
      45                 : #include "nsTArray.h"
      46                 : #include "nsThreadUtils.h"
      47                 : #include "nsClassHashtable.h"
      48                 : #include "nsDataHashtable.h"
      49                 : #include "nsAutoPtr.h"
      50                 : #include "mozilla/ReentrantMonitor.h"
      51                 : #include "nsISocketTransportService.h"
      52                 : 
      53                 : #include "nsIObserver.h"
      54                 : #include "nsITimer.h"
      55                 : #include "nsIX509Cert3.h"
      56                 : 
      57                 : class nsHttpPipeline;
      58                 : 
      59                 : //-----------------------------------------------------------------------------
      60                 : 
      61                 : class nsHttpConnectionMgr : public nsIObserver
      62                 : {
      63                 : public:
      64                 :     NS_DECL_ISUPPORTS
      65                 :     NS_DECL_NSIOBSERVER
      66                 : 
      67                 :     // parameter names
      68                 :     enum nsParamName {
      69                 :         MAX_CONNECTIONS,
      70                 :         MAX_CONNECTIONS_PER_HOST,
      71                 :         MAX_CONNECTIONS_PER_PROXY,
      72                 :         MAX_PERSISTENT_CONNECTIONS_PER_HOST,
      73                 :         MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
      74                 :         MAX_REQUEST_DELAY,
      75                 :         MAX_PIPELINED_REQUESTS
      76                 :     };
      77                 : 
      78                 :     //-------------------------------------------------------------------------
      79                 :     // NOTE: functions below may only be called on the main thread.
      80                 :     //-------------------------------------------------------------------------
      81                 : 
      82                 :     nsHttpConnectionMgr();
      83                 : 
      84                 :     nsresult Init(PRUint16 maxConnections,
      85                 :                   PRUint16 maxConnectionsPerHost,
      86                 :                   PRUint16 maxConnectionsPerProxy,
      87                 :                   PRUint16 maxPersistentConnectionsPerHost,
      88                 :                   PRUint16 maxPersistentConnectionsPerProxy,
      89                 :                   PRUint16 maxRequestDelay,
      90                 :                   PRUint16 maxPipelinedRequests);
      91                 :     nsresult Shutdown();
      92                 : 
      93                 :     //-------------------------------------------------------------------------
      94                 :     // NOTE: functions below may be called on any thread.
      95                 :     //-------------------------------------------------------------------------
      96                 : 
      97                 :     // Schedules next pruning of dead connection to happen after
      98                 :     // given time.
      99                 :     void PruneDeadConnectionsAfter(PRUint32 time);
     100                 : 
     101                 :     // Stops timer scheduled for next pruning of dead connections if
     102                 :     // there are no more idle connections or active spdy ones
     103                 :     void ConditionallyStopPruneDeadConnectionsTimer();
     104                 : 
     105                 :     // Stops timer used for the read timeout tick if there are no currently
     106                 :     // active connections.
     107                 :     void ConditionallyStopReadTimeoutTick();
     108                 : 
     109                 :     // adds a transaction to the list of managed transactions.
     110                 :     nsresult AddTransaction(nsHttpTransaction *, PRInt32 priority);
     111                 : 
     112                 :     // called to reschedule the given transaction.  it must already have been
     113                 :     // added to the connection manager via AddTransaction.
     114                 :     nsresult RescheduleTransaction(nsHttpTransaction *, PRInt32 priority);
     115                 : 
     116                 :     // cancels a transaction w/ the given reason.
     117                 :     nsresult CancelTransaction(nsHttpTransaction *, nsresult reason);
     118                 : 
     119                 :     // called to force the connection manager to prune its list of idle
     120                 :     // connections.
     121                 :     nsresult PruneDeadConnections();
     122                 : 
     123                 :     // Close all idle persistent connections and prevent any active connections
     124                 :     // from being reused.
     125                 :     nsresult ClosePersistentConnections();
     126                 : 
     127                 :     // called to get a reference to the socket transport service.  the socket
     128                 :     // transport service is not available when the connection manager is down.
     129                 :     nsresult GetSocketThreadTarget(nsIEventTarget **);
     130                 : 
     131                 :     // called when a connection is done processing a transaction.  if the 
     132                 :     // connection can be reused then it will be added to the idle list, else
     133                 :     // it will be closed.
     134                 :     nsresult ReclaimConnection(nsHttpConnection *conn);
     135                 : 
     136                 :     // called to update a parameter after the connection manager has already
     137                 :     // been initialized.
     138                 :     nsresult UpdateParam(nsParamName name, PRUint16 value);
     139                 : 
     140                 :     // Lookup/Cancel HTTP->SPDY redirections
     141                 :     bool GetSpdyAlternateProtocol(nsACString &key);
     142                 :     void ReportSpdyAlternateProtocol(nsHttpConnection *);
     143                 :     void RemoveSpdyAlternateProtocol(nsACString &key);
     144                 : 
     145                 :     //-------------------------------------------------------------------------
     146                 :     // NOTE: functions below may be called only on the socket thread.
     147                 :     //-------------------------------------------------------------------------
     148                 : 
     149                 :     // removes the next transaction for the specified connection from the
     150                 :     // pending transaction queue.
     151                 :     void AddTransactionToPipeline(nsHttpPipeline *);
     152                 : 
     153                 :     // called to force the transaction queue to be processed once more, giving
     154                 :     // preference to the specified connection.
     155                 :     nsresult ProcessPendingQ(nsHttpConnectionInfo *);
     156                 : 
     157                 :     // This is used to force an idle connection to be closed and removed from
     158                 :     // the idle connection list. It is called when the idle connection detects
     159                 :     // that the network peer has closed the transport.
     160                 :     nsresult CloseIdleConnection(nsHttpConnection *);
     161                 : 
     162                 :     // The connection manager needs to know when a normal HTTP connection has been
     163                 :     // upgraded to SPDY because the dispatch and idle semantics are a little
     164                 :     // bit different.
     165                 :     void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy);
     166                 : 
     167                 : private:
     168                 :     virtual ~nsHttpConnectionMgr();
     169                 :     class nsHalfOpenSocket;
     170                 :     
     171                 :     // nsConnectionEntry
     172                 :     //
     173                 :     // mCT maps connection info hash key to nsConnectionEntry object, which
     174                 :     // contains list of active and idle connections as well as the list of
     175                 :     // pending transactions.
     176                 :     //
     177                 :     struct nsConnectionEntry
     178                 :     {
     179             291 :         nsConnectionEntry(nsHttpConnectionInfo *ci)
     180                 :           : mConnInfo(ci),
     181                 :             mUsingSpdy(false),
     182                 :             mTestedSpdy(false),
     183             291 :             mSpdyPreferred(false)
     184                 :         {
     185             291 :             NS_ADDREF(mConnInfo);
     186             291 :         }
     187                 :         ~nsConnectionEntry();
     188                 : 
     189                 :         nsHttpConnectionInfo        *mConnInfo;
     190                 :         nsTArray<nsHttpTransaction*> mPendingQ;    // pending transaction queue
     191                 :         nsTArray<nsHttpConnection*>  mActiveConns; // active connections
     192                 :         nsTArray<nsHttpConnection*>  mIdleConns;   // idle persistent connections
     193                 :         nsTArray<nsHalfOpenSocket*>  mHalfOpens;
     194                 : 
     195                 :         // Spdy sometimes resolves the address in the socket manager in order
     196                 :         // to re-coalesce sharded HTTP hosts. The dotted decimal address is
     197                 :         // combined with the Anonymous flag from the connection information
     198                 :         // to build the hash key for hosts in the same ip pool.
     199                 :         //
     200                 :         // When a set of hosts are coalesced together one of them is marked
     201                 :         // mSpdyPreferred. The mapping is maintained in the connection mananger
     202                 :         // mSpdyPreferred hash.
     203                 :         //
     204                 :         nsCString mCoalescingKey;
     205                 : 
     206                 :         // To have the UsingSpdy flag means some host with the same connection
     207                 :         // entry has done NPN=spdy/2 at some point. It does not mean every
     208                 :         // connection is currently using spdy.
     209                 :         bool mUsingSpdy;
     210                 : 
     211                 :         // mTestedSpdy is set after NPN negotiation has occurred and we know
     212                 :         // with confidence whether a host speaks spdy or not (which is reflected
     213                 :         // in mUsingSpdy). Before mTestedSpdy is set, handshake parallelism is
     214                 :         // minimized so that we can multiplex on a single spdy connection.
     215                 :         bool mTestedSpdy;
     216                 : 
     217                 :         bool mSpdyPreferred;
     218                 :     };
     219                 : 
     220                 :     // nsConnectionHandle
     221                 :     //
     222                 :     // thin wrapper around a real connection, used to keep track of references
     223                 :     // to the connection to determine when the connection may be reused.  the
     224                 :     // transaction (or pipeline) owns a reference to this handle.  this extra
     225                 :     // layer of indirection greatly simplifies consumer code, avoiding the
     226                 :     // need for consumer code to know when to give the connection back to the
     227                 :     // connection manager.
     228                 :     //
     229                 :     class nsConnectionHandle : public nsAHttpConnection
     230                 :     {
     231                 :     public:
     232                 :         NS_DECL_ISUPPORTS
     233                 :         NS_DECL_NSAHTTPCONNECTION
     234                 : 
     235            2975 :         nsConnectionHandle(nsHttpConnection *conn) { NS_ADDREF(mConn = conn); }
     236                 :         virtual ~nsConnectionHandle();
     237                 : 
     238                 :         nsHttpConnection *mConn;
     239                 :     };
     240                 : 
     241                 :     // nsHalfOpenSocket is used to hold the state of an opening TCP socket
     242                 :     // while we wait for it to establish and bind it to a connection
     243                 : 
     244                 :     class nsHalfOpenSocket : public nsIOutputStreamCallback,
     245                 :                              public nsITransportEventSink,
     246                 :                              public nsIInterfaceRequestor,
     247                 :                              public nsITimerCallback
     248                 :     {
     249                 :     public:
     250                 :         NS_DECL_ISUPPORTS
     251                 :         NS_DECL_NSIOUTPUTSTREAMCALLBACK
     252                 :         NS_DECL_NSITRANSPORTEVENTSINK
     253                 :         NS_DECL_NSIINTERFACEREQUESTOR
     254                 :         NS_DECL_NSITIMERCALLBACK
     255                 : 
     256                 :         nsHalfOpenSocket(nsConnectionEntry *ent,
     257                 :                          nsHttpTransaction *trans);
     258                 :         ~nsHalfOpenSocket();
     259                 :         
     260                 :         nsresult SetupStreams(nsISocketTransport **,
     261                 :                               nsIAsyncInputStream **,
     262                 :                               nsIAsyncOutputStream **,
     263                 :                               bool isBackup);
     264                 :         nsresult SetupPrimaryStreams();
     265                 :         nsresult SetupBackupStreams();
     266                 :         void     SetupBackupTimer();
     267                 :         void     CancelBackupTimer();
     268                 :         void     Abandon();
     269                 :         
     270             110 :         nsHttpTransaction *Transaction() { return mTransaction; }
     271                 : 
     272                 :     private:
     273                 :         nsConnectionEntry              *mEnt;
     274                 :         nsRefPtr<nsHttpTransaction>    mTransaction;
     275                 :         nsCOMPtr<nsISocketTransport>   mSocketTransport;
     276                 :         nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
     277                 :         nsCOMPtr<nsIAsyncInputStream>  mStreamIn;
     278                 : 
     279                 :         // for syn retry
     280                 :         nsCOMPtr<nsITimer>             mSynTimer;
     281                 :         nsCOMPtr<nsISocketTransport>   mBackupTransport;
     282                 :         nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
     283                 :         nsCOMPtr<nsIAsyncInputStream>  mBackupStreamIn;
     284                 :     };
     285                 :     friend class nsHalfOpenSocket;
     286                 : 
     287                 :     //-------------------------------------------------------------------------
     288                 :     // NOTE: these members may be accessed from any thread (use mReentrantMonitor)
     289                 :     //-------------------------------------------------------------------------
     290                 : 
     291                 :     PRInt32                      mRef;
     292                 :     mozilla::ReentrantMonitor    mReentrantMonitor;
     293                 :     nsCOMPtr<nsIEventTarget>     mSocketThreadTarget;
     294                 : 
     295                 :     // connection limits
     296                 :     PRUint16 mMaxConns;
     297                 :     PRUint16 mMaxConnsPerHost;
     298                 :     PRUint16 mMaxConnsPerProxy;
     299                 :     PRUint16 mMaxPersistConnsPerHost;
     300                 :     PRUint16 mMaxPersistConnsPerProxy;
     301                 :     PRUint16 mMaxRequestDelay; // in seconds
     302                 :     PRUint16 mMaxPipelinedRequests;
     303                 : 
     304                 :     bool mIsShuttingDown;
     305                 : 
     306                 :     //-------------------------------------------------------------------------
     307                 :     // NOTE: these members are only accessed on the socket transport thread
     308                 :     //-------------------------------------------------------------------------
     309                 : 
     310                 :     static PLDHashOperator ProcessOneTransactionCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     311                 : 
     312                 :     static PLDHashOperator PruneDeadConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     313                 :     static PLDHashOperator ShutdownPassCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     314                 :     static PLDHashOperator PurgeExcessIdleConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     315                 :     static PLDHashOperator ClosePersistentConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     316                 :     bool     ProcessPendingQForEntry(nsConnectionEntry *);
     317                 :     bool     AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
     318                 :     void     GetConnection(nsConnectionEntry *, nsHttpTransaction *,
     319                 :                            bool, nsHttpConnection **);
     320                 :     nsresult DispatchTransaction(nsConnectionEntry *, nsHttpTransaction *,
     321                 :                                  PRUint8 caps, nsHttpConnection *);
     322                 :     bool     BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
     323                 :     nsresult ProcessNewTransaction(nsHttpTransaction *);
     324                 :     nsresult EnsureSocketThreadTargetIfOnline();
     325                 :     void     ClosePersistentConnections(nsConnectionEntry *ent);
     326                 :     nsresult CreateTransport(nsConnectionEntry *, nsHttpTransaction *);
     327                 :     void     AddActiveConn(nsHttpConnection *, nsConnectionEntry *);
     328                 :     void     StartedConnect();
     329                 :     void     RecvdConnect();
     330                 : 
     331                 :     // Manage the preferred spdy connection entry for this address
     332                 :     nsConnectionEntry *GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry);
     333                 :     void               RemoveSpdyPreferredEnt(nsACString &aDottedDecimal);
     334                 :     nsHttpConnection  *GetSpdyPreferredConn(nsConnectionEntry *ent);
     335                 :     nsDataHashtable<nsCStringHashKey, nsConnectionEntry *>   mSpdyPreferredHash;
     336                 :     nsConnectionEntry *LookupConnectionEntry(nsHttpConnectionInfo *ci,
     337                 :                                              nsHttpConnection *conn,
     338                 :                                              nsHttpTransaction *trans);
     339                 : 
     340                 :     void               ProcessSpdyPendingQ(nsConnectionEntry *ent);
     341                 :     void               ProcessAllSpdyPendingQ();
     342                 :     static PLDHashOperator ProcessSpdyPendingQCB(
     343                 :         const nsACString &key, nsAutoPtr<nsConnectionEntry> &ent,
     344                 :         void *closure);
     345                 : 
     346                 :     // message handlers have this signature
     347                 :     typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(PRInt32, void *);
     348                 : 
     349                 :     // nsConnEvent
     350                 :     //
     351                 :     // subclass of nsRunnable used to marshall events to the socket transport
     352                 :     // thread.  this class is used to implement PostEvent.
     353                 :     //
     354                 :     class nsConnEvent;
     355                 :     friend class nsConnEvent;
     356                 :     class nsConnEvent : public nsRunnable
     357                 :     {
     358                 :     public:
     359            7041 :         nsConnEvent(nsHttpConnectionMgr *mgr,
     360                 :                     nsConnEventHandler handler,
     361                 :                     PRInt32 iparam,
     362                 :                     void *vparam)
     363                 :             : mMgr(mgr)
     364                 :             , mHandler(handler)
     365                 :             , mIParam(iparam)
     366            7041 :             , mVParam(vparam)
     367                 :         {
     368            7041 :             NS_ADDREF(mMgr);
     369            7041 :         }
     370                 : 
     371            7041 :         NS_IMETHOD Run()
     372                 :         {
     373            7041 :             (mMgr->*mHandler)(mIParam, mVParam);
     374            7041 :             return NS_OK;
     375                 :         }
     376                 : 
     377                 :     private:
     378           14082 :         virtual ~nsConnEvent()
     379           14082 :         {
     380            7041 :             NS_RELEASE(mMgr);
     381           28164 :         }
     382                 : 
     383                 :         nsHttpConnectionMgr *mMgr;
     384                 :         nsConnEventHandler   mHandler;
     385                 :         PRInt32              mIParam;
     386                 :         void                *mVParam;
     387                 :     };
     388                 : 
     389                 :     nsresult PostEvent(nsConnEventHandler  handler,
     390                 :                        PRInt32             iparam = 0,
     391                 :                        void               *vparam = nsnull);
     392                 : 
     393                 :     // message handlers
     394                 :     void OnMsgShutdown             (PRInt32, void *);
     395                 :     void OnMsgNewTransaction       (PRInt32, void *);
     396                 :     void OnMsgReschedTransaction   (PRInt32, void *);
     397                 :     void OnMsgCancelTransaction    (PRInt32, void *);
     398                 :     void OnMsgProcessPendingQ      (PRInt32, void *);
     399                 :     void OnMsgPruneDeadConnections (PRInt32, void *);
     400                 :     void OnMsgReclaimConnection    (PRInt32, void *);
     401                 :     void OnMsgUpdateParam          (PRInt32, void *);
     402                 :     void OnMsgClosePersistentConnections (PRInt32, void *);
     403                 : 
     404                 :     // Total number of active connections in all of the ConnectionEntry objects
     405                 :     // that are accessed from mCT connection table.
     406                 :     PRUint16 mNumActiveConns;
     407                 :     // Total number of idle connections in all of the ConnectionEntry objects
     408                 :     // that are accessed from mCT connection table.
     409                 :     PRUint16 mNumIdleConns;
     410                 : 
     411                 :     // Holds time in seconds for next wake-up to prune dead connections. 
     412                 :     PRUint64 mTimeOfNextWakeUp;
     413                 :     // Timer for next pruning of dead connections.
     414                 :     nsCOMPtr<nsITimer> mTimer;
     415                 : 
     416                 :     // A 1s tick to call nsHttpConnection::ReadTimeoutTick on
     417                 :     // active http/1 connections. Disabled when there are no
     418                 :     // active connections.
     419                 :     nsCOMPtr<nsITimer> mReadTimeoutTick;
     420                 :     bool mReadTimeoutTickArmed;
     421                 : 
     422                 :     //
     423                 :     // the connection table
     424                 :     //
     425                 :     // this table is indexed by connection key.  each entry is a
     426                 :     // nsConnectionEntry object.
     427                 :     //
     428                 :     nsClassHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
     429                 : 
     430                 :     // mAlternateProtocolHash is used only for spdy/2 upgrades for now
     431                 :     // protected by the monitor
     432                 :     nsTHashtable<nsCStringHashKey> mAlternateProtocolHash;
     433                 :     static PLDHashOperator TrimAlternateProtocolHash(nsCStringHashKey *entry,
     434                 :                                                      void *closure);
     435                 :     // Read Timeout Tick handlers
     436                 :     void ActivateTimeoutTick();
     437                 :     void ReadTimeoutTick();
     438                 :     static PLDHashOperator ReadTimeoutTickCB(const nsACString &key,
     439                 :                                              nsAutoPtr<nsConnectionEntry> &ent,
     440                 :                                              void *closure);
     441                 : };
     442                 : 
     443                 : #endif // !nsHttpConnectionMgr_h__

Generated by: LCOV version 1.7