netwerk/protocol/websocket/WebSocketChannel.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/protocol/websocket/WebSocketChannel.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,297 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set sw=2 ts=8 et tw=80 : */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef mozilla_net_WebSocketChannel_h
    1.11 +#define mozilla_net_WebSocketChannel_h
    1.12 +
    1.13 +#include "nsISupports.h"
    1.14 +#include "nsIInterfaceRequestor.h"
    1.15 +#include "nsIStreamListener.h"
    1.16 +#include "nsIAsyncInputStream.h"
    1.17 +#include "nsIAsyncOutputStream.h"
    1.18 +#include "nsITimer.h"
    1.19 +#include "nsIDNSListener.h"
    1.20 +#include "nsIProtocolProxyCallback.h"
    1.21 +#include "nsIChannelEventSink.h"
    1.22 +#include "nsIHttpChannelInternal.h"
    1.23 +#include "BaseWebSocketChannel.h"
    1.24 +
    1.25 +#ifdef MOZ_WIDGET_GONK
    1.26 +#include "nsINetworkManager.h"
    1.27 +#include "nsProxyRelease.h"
    1.28 +#endif
    1.29 +
    1.30 +#include "nsCOMPtr.h"
    1.31 +#include "nsString.h"
    1.32 +#include "nsDeque.h"
    1.33 +
    1.34 +class nsIAsyncVerifyRedirectCallback;
    1.35 +class nsIDashboardEventNotifier;
    1.36 +class nsIEventTarget;
    1.37 +class nsIHttpChannel;
    1.38 +class nsIRandomGenerator;
    1.39 +class nsISocketTransport;
    1.40 +class nsIURI;
    1.41 +
    1.42 +namespace mozilla { namespace net {
    1.43 +
    1.44 +class OutboundMessage;
    1.45 +class OutboundEnqueuer;
    1.46 +class nsWSAdmissionManager;
    1.47 +class nsWSCompression;
    1.48 +class CallOnMessageAvailable;
    1.49 +class CallOnStop;
    1.50 +class CallOnServerClose;
    1.51 +class CallAcknowledge;
    1.52 +
    1.53 +// Used to enforce "1 connecting websocket per host" rule, and reconnect delays
    1.54 +enum wsConnectingState {
    1.55 +  NOT_CONNECTING = 0,     // Not yet (or no longer) trying to open connection
    1.56 +  CONNECTING_QUEUED,      // Waiting for other ws to same host to finish opening
    1.57 +  CONNECTING_DELAYED,     // Delayed by "reconnect after failure" algorithm
    1.58 +  CONNECTING_IN_PROGRESS  // Started connection: waiting for result
    1.59 +};
    1.60 +
    1.61 +class WebSocketChannel : public BaseWebSocketChannel,
    1.62 +                         public nsIHttpUpgradeListener,
    1.63 +                         public nsIStreamListener,
    1.64 +                         public nsIInputStreamCallback,
    1.65 +                         public nsIOutputStreamCallback,
    1.66 +                         public nsITimerCallback,
    1.67 +                         public nsIDNSListener,
    1.68 +                         public nsIProtocolProxyCallback,
    1.69 +                         public nsIInterfaceRequestor,
    1.70 +                         public nsIChannelEventSink
    1.71 +{
    1.72 +public:
    1.73 +  NS_DECL_THREADSAFE_ISUPPORTS
    1.74 +  NS_DECL_NSIHTTPUPGRADELISTENER
    1.75 +  NS_DECL_NSIREQUESTOBSERVER
    1.76 +  NS_DECL_NSISTREAMLISTENER
    1.77 +  NS_DECL_NSIINPUTSTREAMCALLBACK
    1.78 +  NS_DECL_NSIOUTPUTSTREAMCALLBACK
    1.79 +  NS_DECL_NSITIMERCALLBACK
    1.80 +  NS_DECL_NSIDNSLISTENER
    1.81 +  NS_DECL_NSIPROTOCOLPROXYCALLBACK
    1.82 +  NS_DECL_NSIINTERFACEREQUESTOR
    1.83 +  NS_DECL_NSICHANNELEVENTSINK
    1.84 +
    1.85 +  // nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
    1.86 +  //
    1.87 +  NS_IMETHOD AsyncOpen(nsIURI *aURI,
    1.88 +                       const nsACString &aOrigin,
    1.89 +                       nsIWebSocketListener *aListener,
    1.90 +                       nsISupports *aContext);
    1.91 +  NS_IMETHOD Close(uint16_t aCode, const nsACString & aReason);
    1.92 +  NS_IMETHOD SendMsg(const nsACString &aMsg);
    1.93 +  NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
    1.94 +  NS_IMETHOD SendBinaryStream(nsIInputStream *aStream, uint32_t length);
    1.95 +  NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
    1.96 +
    1.97 +  WebSocketChannel();
    1.98 +  static void Shutdown();
    1.99 +
   1.100 +  enum {
   1.101 +    // Non Control Frames
   1.102 +    kContinuation = 0x0,
   1.103 +    kText =         0x1,
   1.104 +    kBinary =       0x2,
   1.105 +
   1.106 +    // Control Frames
   1.107 +    kClose =        0x8,
   1.108 +    kPing =         0x9,
   1.109 +    kPong =         0xA
   1.110 +  };
   1.111 +
   1.112 +  const static uint32_t kControlFrameMask   = 0x8;
   1.113 +  const static uint8_t kMaskBit             = 0x80;
   1.114 +  const static uint8_t kFinalFragBit        = 0x80;
   1.115 +
   1.116 +protected:
   1.117 +  virtual ~WebSocketChannel();
   1.118 +
   1.119 +private:
   1.120 +  friend class OutboundEnqueuer;
   1.121 +  friend class nsWSAdmissionManager;
   1.122 +  friend class FailDelayManager;
   1.123 +  friend class CallOnMessageAvailable;
   1.124 +  friend class CallOnStop;
   1.125 +  friend class CallOnServerClose;
   1.126 +  friend class CallAcknowledge;
   1.127 +
   1.128 +  // Common send code for binary + text msgs
   1.129 +  nsresult SendMsgCommon(const nsACString *aMsg, bool isBinary,
   1.130 +                         uint32_t length, nsIInputStream *aStream = nullptr);
   1.131 +
   1.132 +  void EnqueueOutgoingMessage(nsDeque &aQueue, OutboundMessage *aMsg);
   1.133 +
   1.134 +  void PrimeNewOutgoingMessage();
   1.135 +  void DeleteCurrentOutGoingMessage();
   1.136 +  void GeneratePong(uint8_t *payload, uint32_t len);
   1.137 +  void GeneratePing();
   1.138 +
   1.139 +  void     BeginOpen();
   1.140 +  nsresult HandleExtensions();
   1.141 +  nsresult SetupRequest();
   1.142 +  nsresult ApplyForAdmission();
   1.143 +  nsresult DoAdmissionDNS();
   1.144 +  nsresult StartWebsocketData();
   1.145 +  uint16_t ResultToCloseCode(nsresult resultCode);
   1.146 +  void     ReportConnectionTelemetry();
   1.147 +
   1.148 +  void StopSession(nsresult reason);
   1.149 +  void AbortSession(nsresult reason);
   1.150 +  void ReleaseSession();
   1.151 +  void CleanupConnection();
   1.152 +  void IncrementSessionCount();
   1.153 +  void DecrementSessionCount();
   1.154 +
   1.155 +  void EnsureHdrOut(uint32_t size);
   1.156 +  void ApplyMask(uint32_t mask, uint8_t *data, uint64_t len);
   1.157 +
   1.158 +  bool     IsPersistentFramePtr();
   1.159 +  nsresult ProcessInput(uint8_t *buffer, uint32_t count);
   1.160 +  bool UpdateReadBuffer(uint8_t *buffer, uint32_t count,
   1.161 +                        uint32_t accumulatedFragments,
   1.162 +                        uint32_t *available);
   1.163 +
   1.164 +  inline void ResetPingTimer()
   1.165 +  {
   1.166 +    if (mPingTimer) {
   1.167 +      mPingOutstanding = 0;
   1.168 +      mPingTimer->SetDelay(mPingInterval);
   1.169 +    }
   1.170 +  }
   1.171 +
   1.172 +  nsCOMPtr<nsIEventTarget>                 mSocketThread;
   1.173 +  nsCOMPtr<nsIHttpChannelInternal>         mChannel;
   1.174 +  nsCOMPtr<nsIHttpChannel>                 mHttpChannel;
   1.175 +  nsCOMPtr<nsICancelable>                  mCancelable;
   1.176 +  nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   1.177 +  nsCOMPtr<nsIRandomGenerator>             mRandomGenerator;
   1.178 +
   1.179 +  nsCString                       mHashedSecret;
   1.180 +
   1.181 +  // Used as key for connection managment: Initially set to hostname from URI,
   1.182 +  // then to IP address (unless we're leaving DNS resolution to a proxy server)
   1.183 +  nsCString                       mAddress;
   1.184 +  int32_t                         mPort;          // WS server port
   1.185 +
   1.186 +  // Used for off main thread access to the URI string.
   1.187 +  nsCString                       mHost;
   1.188 +
   1.189 +  nsCOMPtr<nsISocketTransport>    mTransport;
   1.190 +  nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
   1.191 +  nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
   1.192 +
   1.193 +  nsCOMPtr<nsITimer>              mCloseTimer;
   1.194 +  uint32_t                        mCloseTimeout;  /* milliseconds */
   1.195 +
   1.196 +  nsCOMPtr<nsITimer>              mOpenTimer;
   1.197 +  uint32_t                        mOpenTimeout;  /* milliseconds */
   1.198 +  wsConnectingState               mConnecting;   /* 0 if not connecting */
   1.199 +  nsCOMPtr<nsITimer>              mReconnectDelayTimer;
   1.200 +
   1.201 +  nsCOMPtr<nsITimer>              mPingTimer;
   1.202 +
   1.203 +  nsCOMPtr<nsITimer>              mLingeringCloseTimer;
   1.204 +  const static int32_t            kLingeringCloseTimeout =   1000;
   1.205 +  const static int32_t            kLingeringCloseThreshold = 50;
   1.206 +
   1.207 +  int32_t                         mMaxConcurrentConnections;
   1.208 +
   1.209 +  uint32_t                        mGotUpgradeOK              : 1;
   1.210 +  uint32_t                        mRecvdHttpUpgradeTransport : 1;
   1.211 +  uint32_t                        mRequestedClose            : 1;
   1.212 +  uint32_t                        mClientClosed              : 1;
   1.213 +  uint32_t                        mServerClosed              : 1;
   1.214 +  uint32_t                        mStopped                   : 1;
   1.215 +  uint32_t                        mCalledOnStop              : 1;
   1.216 +  uint32_t                        mPingOutstanding           : 1;
   1.217 +  uint32_t                        mAllowCompression          : 1;
   1.218 +  uint32_t                        mAutoFollowRedirects       : 1;
   1.219 +  uint32_t                        mReleaseOnTransmit         : 1;
   1.220 +  uint32_t                        mTCPClosed                 : 1;
   1.221 +  uint32_t                        mOpenedHttpChannel         : 1;
   1.222 +  uint32_t                        mDataStarted               : 1;
   1.223 +  uint32_t                        mIncrementedSessionCount   : 1;
   1.224 +  uint32_t                        mDecrementedSessionCount   : 1;
   1.225 +
   1.226 +  int32_t                         mMaxMessageSize;
   1.227 +  nsresult                        mStopOnClose;
   1.228 +  uint16_t                        mServerCloseCode;
   1.229 +  nsCString                       mServerCloseReason;
   1.230 +  uint16_t                        mScriptCloseCode;
   1.231 +  nsCString                       mScriptCloseReason;
   1.232 +
   1.233 +  // These are for the read buffers
   1.234 +  const static uint32_t kIncomingBufferInitialSize = 16 * 1024;
   1.235 +  // We're ok with keeping a buffer this size or smaller around for the life of
   1.236 +  // the websocket.  If a particular message needs bigger than this we'll
   1.237 +  // increase the buffer temporarily, then drop back down to this size.
   1.238 +  const static uint32_t kIncomingBufferStableSize = 128 * 1024;
   1.239 +
   1.240 +  uint8_t                        *mFramePtr;
   1.241 +  uint8_t                        *mBuffer;
   1.242 +  uint8_t                         mFragmentOpcode;
   1.243 +  uint32_t                        mFragmentAccumulator;
   1.244 +  uint32_t                        mBuffered;
   1.245 +  uint32_t                        mBufferSize;
   1.246 +  nsCOMPtr<nsIStreamListener>     mInflateReader;
   1.247 +  nsCOMPtr<nsIStringInputStream>  mInflateStream;
   1.248 +
   1.249 +  // These are for the send buffers
   1.250 +  const static int32_t kCopyBreak = 1000;
   1.251 +
   1.252 +  OutboundMessage                *mCurrentOut;
   1.253 +  uint32_t                        mCurrentOutSent;
   1.254 +  nsDeque                         mOutgoingMessages;
   1.255 +  nsDeque                         mOutgoingPingMessages;
   1.256 +  nsDeque                         mOutgoingPongMessages;
   1.257 +  uint32_t                        mHdrOutToSend;
   1.258 +  uint8_t                        *mHdrOut;
   1.259 +  uint8_t                         mOutHeader[kCopyBreak + 16];
   1.260 +  nsWSCompression                *mCompressor;
   1.261 +  uint32_t                        mDynamicOutputSize;
   1.262 +  uint8_t                        *mDynamicOutput;
   1.263 +  bool                            mPrivateBrowsing;
   1.264 +
   1.265 +  nsCOMPtr<nsIDashboardEventNotifier> mConnectionLogService;
   1.266 +  uint32_t mSerial;
   1.267 +  static uint32_t sSerialSeed;
   1.268 +
   1.269 +// These members are used for network per-app metering (bug 855949)
   1.270 +// Currently, they are only available on gonk.
   1.271 +  uint64_t                        mCountRecv;
   1.272 +  uint64_t                        mCountSent;
   1.273 +  uint32_t                        mAppId;
   1.274 +#ifdef MOZ_WIDGET_GONK
   1.275 +  nsMainThreadPtrHandle<nsINetworkInterface> mActiveNetwork;
   1.276 +#endif
   1.277 +  nsresult                        SaveNetworkStats(bool);
   1.278 +  void                            CountRecvBytes(uint64_t recvBytes)
   1.279 +  {
   1.280 +    mCountRecv += recvBytes;
   1.281 +    SaveNetworkStats(false);
   1.282 +  }
   1.283 +  void                            CountSentBytes(uint64_t sentBytes)
   1.284 +  {
   1.285 +    mCountSent += sentBytes;
   1.286 +    SaveNetworkStats(false);
   1.287 +  }
   1.288 +};
   1.289 +
   1.290 +class WebSocketSSLChannel : public WebSocketChannel
   1.291 +{
   1.292 +public:
   1.293 +    WebSocketSSLChannel() { BaseWebSocketChannel::mEncrypted = true; }
   1.294 +protected:
   1.295 +    virtual ~WebSocketSSLChannel() {}
   1.296 +};
   1.297 +
   1.298 +}} // namespace mozilla::net
   1.299 +
   1.300 +#endif // mozilla_net_WebSocketChannel_h

mercurial