netwerk/protocol/websocket/WebSocketChannel.h

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     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 #ifndef mozilla_net_WebSocketChannel_h
     8 #define mozilla_net_WebSocketChannel_h
    10 #include "nsISupports.h"
    11 #include "nsIInterfaceRequestor.h"
    12 #include "nsIStreamListener.h"
    13 #include "nsIAsyncInputStream.h"
    14 #include "nsIAsyncOutputStream.h"
    15 #include "nsITimer.h"
    16 #include "nsIDNSListener.h"
    17 #include "nsIProtocolProxyCallback.h"
    18 #include "nsIChannelEventSink.h"
    19 #include "nsIHttpChannelInternal.h"
    20 #include "BaseWebSocketChannel.h"
    22 #ifdef MOZ_WIDGET_GONK
    23 #include "nsINetworkManager.h"
    24 #include "nsProxyRelease.h"
    25 #endif
    27 #include "nsCOMPtr.h"
    28 #include "nsString.h"
    29 #include "nsDeque.h"
    31 class nsIAsyncVerifyRedirectCallback;
    32 class nsIDashboardEventNotifier;
    33 class nsIEventTarget;
    34 class nsIHttpChannel;
    35 class nsIRandomGenerator;
    36 class nsISocketTransport;
    37 class nsIURI;
    39 namespace mozilla { namespace net {
    41 class OutboundMessage;
    42 class OutboundEnqueuer;
    43 class nsWSAdmissionManager;
    44 class nsWSCompression;
    45 class CallOnMessageAvailable;
    46 class CallOnStop;
    47 class CallOnServerClose;
    48 class CallAcknowledge;
    50 // Used to enforce "1 connecting websocket per host" rule, and reconnect delays
    51 enum wsConnectingState {
    52   NOT_CONNECTING = 0,     // Not yet (or no longer) trying to open connection
    53   CONNECTING_QUEUED,      // Waiting for other ws to same host to finish opening
    54   CONNECTING_DELAYED,     // Delayed by "reconnect after failure" algorithm
    55   CONNECTING_IN_PROGRESS  // Started connection: waiting for result
    56 };
    58 class WebSocketChannel : public BaseWebSocketChannel,
    59                          public nsIHttpUpgradeListener,
    60                          public nsIStreamListener,
    61                          public nsIInputStreamCallback,
    62                          public nsIOutputStreamCallback,
    63                          public nsITimerCallback,
    64                          public nsIDNSListener,
    65                          public nsIProtocolProxyCallback,
    66                          public nsIInterfaceRequestor,
    67                          public nsIChannelEventSink
    68 {
    69 public:
    70   NS_DECL_THREADSAFE_ISUPPORTS
    71   NS_DECL_NSIHTTPUPGRADELISTENER
    72   NS_DECL_NSIREQUESTOBSERVER
    73   NS_DECL_NSISTREAMLISTENER
    74   NS_DECL_NSIINPUTSTREAMCALLBACK
    75   NS_DECL_NSIOUTPUTSTREAMCALLBACK
    76   NS_DECL_NSITIMERCALLBACK
    77   NS_DECL_NSIDNSLISTENER
    78   NS_DECL_NSIPROTOCOLPROXYCALLBACK
    79   NS_DECL_NSIINTERFACEREQUESTOR
    80   NS_DECL_NSICHANNELEVENTSINK
    82   // nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
    83   //
    84   NS_IMETHOD AsyncOpen(nsIURI *aURI,
    85                        const nsACString &aOrigin,
    86                        nsIWebSocketListener *aListener,
    87                        nsISupports *aContext);
    88   NS_IMETHOD Close(uint16_t aCode, const nsACString & aReason);
    89   NS_IMETHOD SendMsg(const nsACString &aMsg);
    90   NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
    91   NS_IMETHOD SendBinaryStream(nsIInputStream *aStream, uint32_t length);
    92   NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
    94   WebSocketChannel();
    95   static void Shutdown();
    97   enum {
    98     // Non Control Frames
    99     kContinuation = 0x0,
   100     kText =         0x1,
   101     kBinary =       0x2,
   103     // Control Frames
   104     kClose =        0x8,
   105     kPing =         0x9,
   106     kPong =         0xA
   107   };
   109   const static uint32_t kControlFrameMask   = 0x8;
   110   const static uint8_t kMaskBit             = 0x80;
   111   const static uint8_t kFinalFragBit        = 0x80;
   113 protected:
   114   virtual ~WebSocketChannel();
   116 private:
   117   friend class OutboundEnqueuer;
   118   friend class nsWSAdmissionManager;
   119   friend class FailDelayManager;
   120   friend class CallOnMessageAvailable;
   121   friend class CallOnStop;
   122   friend class CallOnServerClose;
   123   friend class CallAcknowledge;
   125   // Common send code for binary + text msgs
   126   nsresult SendMsgCommon(const nsACString *aMsg, bool isBinary,
   127                          uint32_t length, nsIInputStream *aStream = nullptr);
   129   void EnqueueOutgoingMessage(nsDeque &aQueue, OutboundMessage *aMsg);
   131   void PrimeNewOutgoingMessage();
   132   void DeleteCurrentOutGoingMessage();
   133   void GeneratePong(uint8_t *payload, uint32_t len);
   134   void GeneratePing();
   136   void     BeginOpen();
   137   nsresult HandleExtensions();
   138   nsresult SetupRequest();
   139   nsresult ApplyForAdmission();
   140   nsresult DoAdmissionDNS();
   141   nsresult StartWebsocketData();
   142   uint16_t ResultToCloseCode(nsresult resultCode);
   143   void     ReportConnectionTelemetry();
   145   void StopSession(nsresult reason);
   146   void AbortSession(nsresult reason);
   147   void ReleaseSession();
   148   void CleanupConnection();
   149   void IncrementSessionCount();
   150   void DecrementSessionCount();
   152   void EnsureHdrOut(uint32_t size);
   153   void ApplyMask(uint32_t mask, uint8_t *data, uint64_t len);
   155   bool     IsPersistentFramePtr();
   156   nsresult ProcessInput(uint8_t *buffer, uint32_t count);
   157   bool UpdateReadBuffer(uint8_t *buffer, uint32_t count,
   158                         uint32_t accumulatedFragments,
   159                         uint32_t *available);
   161   inline void ResetPingTimer()
   162   {
   163     if (mPingTimer) {
   164       mPingOutstanding = 0;
   165       mPingTimer->SetDelay(mPingInterval);
   166     }
   167   }
   169   nsCOMPtr<nsIEventTarget>                 mSocketThread;
   170   nsCOMPtr<nsIHttpChannelInternal>         mChannel;
   171   nsCOMPtr<nsIHttpChannel>                 mHttpChannel;
   172   nsCOMPtr<nsICancelable>                  mCancelable;
   173   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   174   nsCOMPtr<nsIRandomGenerator>             mRandomGenerator;
   176   nsCString                       mHashedSecret;
   178   // Used as key for connection managment: Initially set to hostname from URI,
   179   // then to IP address (unless we're leaving DNS resolution to a proxy server)
   180   nsCString                       mAddress;
   181   int32_t                         mPort;          // WS server port
   183   // Used for off main thread access to the URI string.
   184   nsCString                       mHost;
   186   nsCOMPtr<nsISocketTransport>    mTransport;
   187   nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
   188   nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
   190   nsCOMPtr<nsITimer>              mCloseTimer;
   191   uint32_t                        mCloseTimeout;  /* milliseconds */
   193   nsCOMPtr<nsITimer>              mOpenTimer;
   194   uint32_t                        mOpenTimeout;  /* milliseconds */
   195   wsConnectingState               mConnecting;   /* 0 if not connecting */
   196   nsCOMPtr<nsITimer>              mReconnectDelayTimer;
   198   nsCOMPtr<nsITimer>              mPingTimer;
   200   nsCOMPtr<nsITimer>              mLingeringCloseTimer;
   201   const static int32_t            kLingeringCloseTimeout =   1000;
   202   const static int32_t            kLingeringCloseThreshold = 50;
   204   int32_t                         mMaxConcurrentConnections;
   206   uint32_t                        mGotUpgradeOK              : 1;
   207   uint32_t                        mRecvdHttpUpgradeTransport : 1;
   208   uint32_t                        mRequestedClose            : 1;
   209   uint32_t                        mClientClosed              : 1;
   210   uint32_t                        mServerClosed              : 1;
   211   uint32_t                        mStopped                   : 1;
   212   uint32_t                        mCalledOnStop              : 1;
   213   uint32_t                        mPingOutstanding           : 1;
   214   uint32_t                        mAllowCompression          : 1;
   215   uint32_t                        mAutoFollowRedirects       : 1;
   216   uint32_t                        mReleaseOnTransmit         : 1;
   217   uint32_t                        mTCPClosed                 : 1;
   218   uint32_t                        mOpenedHttpChannel         : 1;
   219   uint32_t                        mDataStarted               : 1;
   220   uint32_t                        mIncrementedSessionCount   : 1;
   221   uint32_t                        mDecrementedSessionCount   : 1;
   223   int32_t                         mMaxMessageSize;
   224   nsresult                        mStopOnClose;
   225   uint16_t                        mServerCloseCode;
   226   nsCString                       mServerCloseReason;
   227   uint16_t                        mScriptCloseCode;
   228   nsCString                       mScriptCloseReason;
   230   // These are for the read buffers
   231   const static uint32_t kIncomingBufferInitialSize = 16 * 1024;
   232   // We're ok with keeping a buffer this size or smaller around for the life of
   233   // the websocket.  If a particular message needs bigger than this we'll
   234   // increase the buffer temporarily, then drop back down to this size.
   235   const static uint32_t kIncomingBufferStableSize = 128 * 1024;
   237   uint8_t                        *mFramePtr;
   238   uint8_t                        *mBuffer;
   239   uint8_t                         mFragmentOpcode;
   240   uint32_t                        mFragmentAccumulator;
   241   uint32_t                        mBuffered;
   242   uint32_t                        mBufferSize;
   243   nsCOMPtr<nsIStreamListener>     mInflateReader;
   244   nsCOMPtr<nsIStringInputStream>  mInflateStream;
   246   // These are for the send buffers
   247   const static int32_t kCopyBreak = 1000;
   249   OutboundMessage                *mCurrentOut;
   250   uint32_t                        mCurrentOutSent;
   251   nsDeque                         mOutgoingMessages;
   252   nsDeque                         mOutgoingPingMessages;
   253   nsDeque                         mOutgoingPongMessages;
   254   uint32_t                        mHdrOutToSend;
   255   uint8_t                        *mHdrOut;
   256   uint8_t                         mOutHeader[kCopyBreak + 16];
   257   nsWSCompression                *mCompressor;
   258   uint32_t                        mDynamicOutputSize;
   259   uint8_t                        *mDynamicOutput;
   260   bool                            mPrivateBrowsing;
   262   nsCOMPtr<nsIDashboardEventNotifier> mConnectionLogService;
   263   uint32_t mSerial;
   264   static uint32_t sSerialSeed;
   266 // These members are used for network per-app metering (bug 855949)
   267 // Currently, they are only available on gonk.
   268   uint64_t                        mCountRecv;
   269   uint64_t                        mCountSent;
   270   uint32_t                        mAppId;
   271 #ifdef MOZ_WIDGET_GONK
   272   nsMainThreadPtrHandle<nsINetworkInterface> mActiveNetwork;
   273 #endif
   274   nsresult                        SaveNetworkStats(bool);
   275   void                            CountRecvBytes(uint64_t recvBytes)
   276   {
   277     mCountRecv += recvBytes;
   278     SaveNetworkStats(false);
   279   }
   280   void                            CountSentBytes(uint64_t sentBytes)
   281   {
   282     mCountSent += sentBytes;
   283     SaveNetworkStats(false);
   284   }
   285 };
   287 class WebSocketSSLChannel : public WebSocketChannel
   288 {
   289 public:
   290     WebSocketSSLChannel() { BaseWebSocketChannel::mEncrypted = true; }
   291 protected:
   292     virtual ~WebSocketSSLChannel() {}
   293 };
   295 }} // namespace mozilla::net
   297 #endif // mozilla_net_WebSocketChannel_h

mercurial