netwerk/protocol/websocket/WebSocketChannel.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial