Thu, 15 Jan 2015 15:55:04 +0100
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