Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/net/WebSocketChannel.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#ifndef mozilla_net_WebSocketChannel_h
8
#define mozilla_net_WebSocketChannel_h
9
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 "nsINamed.h"
18
#include "nsIObserver.h"
19
#include "nsIProtocolProxyCallback.h"
20
#include "nsIChannelEventSink.h"
21
#include "nsIHttpChannelInternal.h"
22
#include "nsIStringStream.h"
23
#include "BaseWebSocketChannel.h"
24
25
#include "nsCOMPtr.h"
26
#include "nsString.h"
27
#include "nsDeque.h"
28
#include "mozilla/Atomics.h"
29
30
class nsIAsyncVerifyRedirectCallback;
31
class nsIDashboardEventNotifier;
32
class nsIEventTarget;
33
class nsIHttpChannel;
34
class nsIRandomGenerator;
35
class nsISocketTransport;
36
class nsIURI;
37
38
namespace mozilla {
39
namespace net {
40
41
class OutboundMessage;
42
class OutboundEnqueuer;
43
class nsWSAdmissionManager;
44
class PMCECompression;
45
class CallOnMessageAvailable;
46
class CallOnStop;
47
class CallOnServerClose;
48
class CallAcknowledge;
49
class WebSocketEventService;
50
51
extern MOZ_MUST_USE nsresult
52
CalculateWebSocketHashedSecret(const nsACString& aKey, nsACString& aHash);
53
extern void
54
ProcessServerWebSocketExtensions(const nsACString& aExtensions,
55
                                 nsACString& aNegotiatedExtensions);
56
57
// Used to enforce "1 connecting websocket per host" rule, and reconnect delays
58
enum wsConnectingState {
59
  NOT_CONNECTING = 0,     // Not yet (or no longer) trying to open connection
60
  CONNECTING_QUEUED,      // Waiting for other ws to same host to finish opening
61
  CONNECTING_DELAYED,     // Delayed by "reconnect after failure" algorithm
62
  CONNECTING_IN_PROGRESS  // Started connection: waiting for result
63
};
64
65
class WebSocketChannel : public BaseWebSocketChannel,
66
                         public nsIHttpUpgradeListener,
67
                         public nsIStreamListener,
68
                         public nsIInputStreamCallback,
69
                         public nsIOutputStreamCallback,
70
                         public nsITimerCallback,
71
                         public nsIDNSListener,
72
                         public nsIObserver,
73
                         public nsIProtocolProxyCallback,
74
                         public nsIInterfaceRequestor,
75
                         public nsIChannelEventSink,
76
                         public nsINamed
77
{
78
  friend class WebSocketFrame;
79
80
public:
81
  NS_DECL_THREADSAFE_ISUPPORTS
82
  NS_DECL_NSIHTTPUPGRADELISTENER
83
  NS_DECL_NSIREQUESTOBSERVER
84
  NS_DECL_NSISTREAMLISTENER
85
  NS_DECL_NSIINPUTSTREAMCALLBACK
86
  NS_DECL_NSIOUTPUTSTREAMCALLBACK
87
  NS_DECL_NSITIMERCALLBACK
88
  NS_DECL_NSIDNSLISTENER
89
  NS_DECL_NSIPROTOCOLPROXYCALLBACK
90
  NS_DECL_NSIINTERFACEREQUESTOR
91
  NS_DECL_NSICHANNELEVENTSINK
92
  NS_DECL_NSIOBSERVER
93
  NS_DECL_NSINAMED
94
95
  // nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
96
  //
97
  NS_IMETHOD AsyncOpen(nsIURI *aURI,
98
                       const nsACString &aOrigin,
99
                       uint64_t aWindowID,
100
                       nsIWebSocketListener *aListener,
101
                       nsISupports *aContext) override;
102
  NS_IMETHOD Close(uint16_t aCode, const nsACString & aReason) override;
103
  NS_IMETHOD SendMsg(const nsACString &aMsg) override;
104
  NS_IMETHOD SendBinaryMsg(const nsACString &aMsg) override;
105
  NS_IMETHOD SendBinaryStream(nsIInputStream *aStream, uint32_t length) override;
106
  NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override;
107
108
  WebSocketChannel();
109
  static void Shutdown();
110
  bool IsOnTargetThread();
111
112
  // Off main thread URI access.
113
  void GetEffectiveURL(nsAString& aEffectiveURL) const override;
114
  bool IsEncrypted() const override;
115
116
  const static uint32_t kControlFrameMask   = 0x8;
117
118
  // First byte of the header
119
  const static uint8_t kFinalFragBit        = 0x80;
120
  const static uint8_t kRsvBitsMask         = 0x70;
121
  const static uint8_t kRsv1Bit             = 0x40;
122
  const static uint8_t kRsv2Bit             = 0x20;
123
  const static uint8_t kRsv3Bit             = 0x10;
124
  const static uint8_t kOpcodeBitsMask      = 0x0F;
125
126
  // Second byte of the header
127
  const static uint8_t kMaskBit             = 0x80;
128
  const static uint8_t kPayloadLengthBitsMask = 0x7F;
129
130
protected:
131
  virtual ~WebSocketChannel();
132
133
private:
134
  friend class OutboundEnqueuer;
135
  friend class nsWSAdmissionManager;
136
  friend class FailDelayManager;
137
  friend class CallOnMessageAvailable;
138
  friend class CallOnStop;
139
  friend class CallOnServerClose;
140
  friend class CallAcknowledge;
141
142
  // Common send code for binary + text msgs
143
  MOZ_MUST_USE nsresult SendMsgCommon(const nsACString *aMsg, bool isBinary,
144
                                      uint32_t length,
145
                                      nsIInputStream *aStream = nullptr);
146
147
  void EnqueueOutgoingMessage(nsDeque &aQueue, OutboundMessage *aMsg);
148
149
  void PrimeNewOutgoingMessage();
150
  void DeleteCurrentOutGoingMessage();
151
  void GeneratePong(uint8_t *payload, uint32_t len);
152
  void GeneratePing();
153
154
  MOZ_MUST_USE nsresult OnNetworkChanged();
155
  MOZ_MUST_USE nsresult StartPinging();
156
157
  void     BeginOpen(bool aCalledFromAdmissionManager);
158
  void     BeginOpenInternal();
159
  MOZ_MUST_USE nsresult HandleExtensions();
160
  MOZ_MUST_USE nsresult SetupRequest();
161
  MOZ_MUST_USE nsresult ApplyForAdmission();
162
  MOZ_MUST_USE nsresult DoAdmissionDNS();
163
  MOZ_MUST_USE nsresult StartWebsocketData();
164
  uint16_t ResultToCloseCode(nsresult resultCode);
165
  void     ReportConnectionTelemetry();
166
167
  void StopSession(nsresult reason);
168
  void DoStopSession(nsresult reason);
169
  void AbortSession(nsresult reason);
170
  void ReleaseSession();
171
  void CleanupConnection();
172
  void IncrementSessionCount();
173
  void DecrementSessionCount();
174
175
  void EnsureHdrOut(uint32_t size);
176
177
  static void ApplyMask(uint32_t mask, uint8_t *data, uint64_t len);
178
179
  bool     IsPersistentFramePtr();
180
  MOZ_MUST_USE nsresult ProcessInput(uint8_t *buffer, uint32_t count);
181
  MOZ_MUST_USE bool UpdateReadBuffer(uint8_t *buffer, uint32_t count,
182
                                     uint32_t accumulatedFragments,
183
                                     uint32_t *available);
184
185
  inline void ResetPingTimer()
186
0
  {
187
0
    mPingOutstanding = 0;
188
0
    if (mPingTimer) {
189
0
      if (!mPingInterval) {
190
0
        // The timer was created by forced ping and regular pinging is disabled,
191
0
        // so cancel and null out mPingTimer.
192
0
        mPingTimer->Cancel();
193
0
        mPingTimer = nullptr;
194
0
      } else {
195
0
        mPingTimer->SetDelay(mPingInterval);
196
0
      }
197
0
    }
198
0
  }
199
200
  nsCOMPtr<nsIEventTarget>                 mSocketThread;
201
  nsCOMPtr<nsIHttpChannelInternal>         mChannel;
202
  nsCOMPtr<nsIHttpChannel>                 mHttpChannel;
203
  nsCOMPtr<nsICancelable>                  mCancelable;
204
  nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
205
  nsCOMPtr<nsIRandomGenerator>             mRandomGenerator;
206
207
  nsCString                       mHashedSecret;
208
209
  // Used as key for connection managment: Initially set to hostname from URI,
210
  // then to IP address (unless we're leaving DNS resolution to a proxy server)
211
  nsCString                       mAddress;
212
  int32_t                         mPort;          // WS server port
213
214
  // Used for off main thread access to the URI string.
215
  nsCString                       mHost;
216
  nsString                        mEffectiveURL;
217
218
  nsCOMPtr<nsISocketTransport>    mTransport;
219
  nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
220
  nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
221
222
  nsCOMPtr<nsITimer>              mCloseTimer;
223
  uint32_t                        mCloseTimeout;  /* milliseconds */
224
225
  nsCOMPtr<nsITimer>              mOpenTimer;
226
  uint32_t                        mOpenTimeout;  /* milliseconds */
227
  wsConnectingState               mConnecting;   /* 0 if not connecting */
228
  nsCOMPtr<nsITimer>              mReconnectDelayTimer;
229
230
  nsCOMPtr<nsITimer>              mPingTimer;
231
232
  nsCOMPtr<nsITimer>              mLingeringCloseTimer;
233
  const static int32_t            kLingeringCloseTimeout =   1000;
234
  const static int32_t            kLingeringCloseThreshold = 50;
235
236
  RefPtr<WebSocketEventService>   mService;
237
238
  int32_t                         mMaxConcurrentConnections;
239
240
  uint64_t                        mInnerWindowID;
241
242
  // following members are accessed only on the main thread
243
  uint32_t                        mGotUpgradeOK              : 1;
244
  uint32_t                        mRecvdHttpUpgradeTransport : 1;
245
  uint32_t                        mAutoFollowRedirects       : 1;
246
  uint32_t                        mAllowPMCE                 : 1;
247
  uint32_t                                                   : 0;
248
249
  // following members are accessed only on the socket thread
250
  uint32_t                        mPingOutstanding           : 1;
251
  uint32_t                        mReleaseOnTransmit         : 1;
252
  uint32_t                                                   : 0;
253
254
  Atomic<bool>                    mDataStarted;
255
  Atomic<bool>                    mRequestedClose;
256
  Atomic<bool>                    mClientClosed;
257
  Atomic<bool>                    mServerClosed;
258
  Atomic<bool>                    mStopped;
259
  Atomic<bool>                    mCalledOnStop;
260
  Atomic<bool>                    mTCPClosed;
261
  Atomic<bool>                    mOpenedHttpChannel;
262
  Atomic<bool>                    mIncrementedSessionCount;
263
  Atomic<bool>                    mDecrementedSessionCount;
264
265
  int32_t                         mMaxMessageSize;
266
  nsresult                        mStopOnClose;
267
  uint16_t                        mServerCloseCode;
268
  nsCString                       mServerCloseReason;
269
  uint16_t                        mScriptCloseCode;
270
  nsCString                       mScriptCloseReason;
271
272
  // These are for the read buffers
273
  const static uint32_t kIncomingBufferInitialSize = 16 * 1024;
274
  // We're ok with keeping a buffer this size or smaller around for the life of
275
  // the websocket.  If a particular message needs bigger than this we'll
276
  // increase the buffer temporarily, then drop back down to this size.
277
  const static uint32_t kIncomingBufferStableSize = 128 * 1024;
278
279
  uint8_t                        *mFramePtr;
280
  uint8_t                        *mBuffer;
281
  uint8_t                         mFragmentOpcode;
282
  uint32_t                        mFragmentAccumulator;
283
  uint32_t                        mBuffered;
284
  uint32_t                        mBufferSize;
285
286
  // These are for the send buffers
287
  const static int32_t kCopyBreak = 1000;
288
289
  OutboundMessage                *mCurrentOut;
290
  uint32_t                        mCurrentOutSent;
291
  nsDeque                         mOutgoingMessages;
292
  nsDeque                         mOutgoingPingMessages;
293
  nsDeque                         mOutgoingPongMessages;
294
  uint32_t                        mHdrOutToSend;
295
  uint8_t                        *mHdrOut;
296
  uint8_t                         mOutHeader[kCopyBreak + 16];
297
  nsAutoPtr<PMCECompression>      mPMCECompressor;
298
  uint32_t                        mDynamicOutputSize;
299
  uint8_t                        *mDynamicOutput;
300
  bool                            mPrivateBrowsing;
301
302
  nsCOMPtr<nsIDashboardEventNotifier> mConnectionLogService;
303
304
  mozilla::Mutex mMutex;
305
};
306
307
class WebSocketSSLChannel : public WebSocketChannel
308
{
309
public:
310
    WebSocketSSLChannel() { BaseWebSocketChannel::mEncrypted = true; }
311
protected:
312
    virtual ~WebSocketSSLChannel() = default;
313
};
314
315
} // namespace net
316
} // namespace mozilla
317
318
#endif // mozilla_net_WebSocketChannel_h