Bug 1526591 - Remove devtools.inspector.shapesHighlighter.enabled pref. r=rcaliman
[gecko.git] / netwerk / base / nsSocketTransport2.h
blob904a241557c0c76d7d5514953fcf0347b0546ea5
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef nsSocketTransport2_h__
6 #define nsSocketTransport2_h__
8 #ifdef DEBUG_darinf
9 # define ENABLE_SOCKET_TRACING
10 #endif
12 #include "mozilla/Mutex.h"
13 #include "nsSocketTransportService2.h"
14 #include "nsString.h"
15 #include "nsCOMPtr.h"
17 #include "nsIInterfaceRequestor.h"
18 #include "nsISocketTransport.h"
19 #include "nsIAsyncInputStream.h"
20 #include "nsIAsyncOutputStream.h"
21 #include "nsIDNSListener.h"
22 #include "nsIClassInfo.h"
23 #include "TCPFastOpen.h"
24 #include "mozilla/net/DNS.h"
25 #include "nsASocketHandler.h"
26 #include "mozilla/Telemetry.h"
28 #include "prerror.h"
29 #include "nsAutoPtr.h"
31 class nsICancelable;
32 class nsIDNSRecord;
33 class nsIInterfaceRequestor;
35 //-----------------------------------------------------------------------------
37 // after this short interval, we will return to PR_Poll
38 #define NS_SOCKET_CONNECT_TIMEOUT PR_MillisecondsToInterval(20)
40 //-----------------------------------------------------------------------------
42 namespace mozilla {
43 namespace net {
45 nsresult ErrorAccordingToNSPR(PRErrorCode errorCode);
47 class nsSocketTransport;
49 class nsSocketInputStream : public nsIAsyncInputStream {
50 public:
51 NS_DECL_ISUPPORTS_INHERITED
52 NS_DECL_NSIINPUTSTREAM
53 NS_DECL_NSIASYNCINPUTSTREAM
55 explicit nsSocketInputStream(nsSocketTransport *);
56 virtual ~nsSocketInputStream() = default;
58 bool IsReferenced() { return mReaderRefCnt > 0; }
59 nsresult Condition() { return mCondition; }
60 uint64_t ByteCount() { return mByteCount; }
62 // called by the socket transport on the socket thread...
63 void OnSocketReady(nsresult condition);
65 private:
66 nsSocketTransport *mTransport;
67 ThreadSafeAutoRefCnt mReaderRefCnt;
69 // access to these is protected by mTransport->mLock
70 nsresult mCondition;
71 nsCOMPtr<nsIInputStreamCallback> mCallback;
72 uint32_t mCallbackFlags;
73 uint64_t mByteCount;
76 //-----------------------------------------------------------------------------
78 class nsSocketOutputStream : public nsIAsyncOutputStream {
79 public:
80 NS_DECL_ISUPPORTS_INHERITED
81 NS_DECL_NSIOUTPUTSTREAM
82 NS_DECL_NSIASYNCOUTPUTSTREAM
84 explicit nsSocketOutputStream(nsSocketTransport *);
85 virtual ~nsSocketOutputStream() = default;
87 bool IsReferenced() { return mWriterRefCnt > 0; }
88 nsresult Condition() { return mCondition; }
89 uint64_t ByteCount() { return mByteCount; }
91 // called by the socket transport on the socket thread...
92 void OnSocketReady(nsresult condition);
94 private:
95 static nsresult WriteFromSegments(nsIInputStream *, void *, const char *,
96 uint32_t offset, uint32_t count,
97 uint32_t *countRead);
99 nsSocketTransport *mTransport;
100 ThreadSafeAutoRefCnt mWriterRefCnt;
102 // access to these is protected by mTransport->mLock
103 nsresult mCondition;
104 nsCOMPtr<nsIOutputStreamCallback> mCallback;
105 uint32_t mCallbackFlags;
106 uint64_t mByteCount;
109 //-----------------------------------------------------------------------------
111 class nsSocketTransport final : public nsASocketHandler,
112 public nsISocketTransport,
113 public nsIDNSListener,
114 public nsIClassInfo,
115 public nsIInterfaceRequestor {
116 public:
117 NS_DECL_THREADSAFE_ISUPPORTS
118 NS_DECL_NSITRANSPORT
119 NS_DECL_NSISOCKETTRANSPORT
120 NS_DECL_NSIDNSLISTENER
121 NS_DECL_NSICLASSINFO
122 NS_DECL_NSIINTERFACEREQUESTOR
124 nsSocketTransport();
126 // this method instructs the socket transport to open a socket of the
127 // given type(s) to the given host or proxy.
128 nsresult Init(const char **socketTypes, uint32_t typeCount,
129 const nsACString &host, uint16_t port,
130 const nsACString &hostRoute, uint16_t portRoute,
131 nsIProxyInfo *proxyInfo);
133 // this method instructs the socket transport to use an already connected
134 // socket with the given address.
135 nsresult InitWithConnectedSocket(PRFileDesc *socketFD, const NetAddr *addr);
137 // this method instructs the socket transport to use an already connected
138 // socket with the given address, and additionally supplies security info.
139 nsresult InitWithConnectedSocket(PRFileDesc *aSocketFD, const NetAddr *aAddr,
140 nsISupports *aSecInfo);
142 #ifdef XP_UNIX
143 // This method instructs the socket transport to open a socket
144 // connected to the given Unix domain address. We can only create
145 // unlayered, simple, stream sockets.
146 nsresult InitWithFilename(const char *filename);
148 // This method instructs the socket transport to open a socket
149 // connected to the given Unix domain address that includes abstract
150 // socket address. If using abstract socket address, first character of
151 // name parameter has to be \0.
152 // We can only create unlayered, simple, stream sockets.
153 nsresult InitWithName(const char *name, size_t len);
154 #endif
156 // nsASocketHandler methods:
157 void OnSocketReady(PRFileDesc *, int16_t outFlags) override;
158 void OnSocketDetached(PRFileDesc *) override;
159 void IsLocal(bool *aIsLocal) override;
160 void OnKeepaliveEnabledPrefChange(bool aEnabled) final;
162 // called when a socket event is handled
163 void OnSocketEvent(uint32_t type, nsresult status, nsISupports *param);
165 uint64_t ByteCountReceived() override { return mInput.ByteCount(); }
166 uint64_t ByteCountSent() override { return mOutput.ByteCount(); }
167 static void CloseSocket(PRFileDesc *aFd, bool aTelemetryEnabled);
168 static void SendPRBlockingTelemetry(
169 PRIntervalTime aStart, Telemetry::HistogramID aIDNormal,
170 Telemetry::HistogramID aIDShutdown,
171 Telemetry::HistogramID aIDConnectivityChange,
172 Telemetry::HistogramID aIDLinkChange, Telemetry::HistogramID aIDOffline);
174 protected:
175 virtual ~nsSocketTransport();
176 void CleanupTypes();
178 private:
179 // event types
180 enum {
181 MSG_ENSURE_CONNECT,
182 MSG_DNS_LOOKUP_COMPLETE,
183 MSG_RETRY_INIT_SOCKET,
184 MSG_TIMEOUT_CHANGED,
185 MSG_INPUT_CLOSED,
186 MSG_INPUT_PENDING,
187 MSG_OUTPUT_CLOSED,
188 MSG_OUTPUT_PENDING
190 nsresult PostEvent(uint32_t type, nsresult status = NS_OK,
191 nsISupports *param = nullptr);
193 enum {
194 STATE_CLOSED,
195 STATE_IDLE,
196 STATE_RESOLVING,
197 STATE_CONNECTING,
198 STATE_TRANSFERRING
201 // Safer way to get and automatically release PRFileDesc objects.
202 class MOZ_STACK_CLASS PRFileDescAutoLock {
203 public:
204 explicit PRFileDescAutoLock(nsSocketTransport *aSocketTransport,
205 bool aAlsoDuringFastOpen,
206 nsresult *aConditionWhileLocked = nullptr)
207 : mSocketTransport(aSocketTransport), mFd(nullptr) {
208 MOZ_ASSERT(aSocketTransport);
209 MutexAutoLock lock(mSocketTransport->mLock);
210 if (aConditionWhileLocked) {
211 *aConditionWhileLocked = mSocketTransport->mCondition;
212 if (NS_FAILED(mSocketTransport->mCondition)) {
213 return;
216 if (!aAlsoDuringFastOpen) {
217 mFd = mSocketTransport->GetFD_Locked();
218 } else {
219 mFd = mSocketTransport->GetFD_LockedAlsoDuringFastOpen();
222 ~PRFileDescAutoLock() {
223 MutexAutoLock lock(mSocketTransport->mLock);
224 if (mFd) {
225 mSocketTransport->ReleaseFD_Locked(mFd);
228 bool IsInitialized() { return mFd; }
229 operator PRFileDesc *() { return mFd; }
230 nsresult SetKeepaliveEnabled(bool aEnable);
231 nsresult SetKeepaliveVals(bool aEnabled, int aIdleTime, int aRetryInterval,
232 int aProbeCount);
234 private:
235 operator PRFileDescAutoLock *() { return nullptr; }
237 // Weak ptr to nsSocketTransport since this is a stack class only.
238 nsSocketTransport *mSocketTransport;
239 PRFileDesc *mFd;
241 friend class PRFileDescAutoLock;
243 class LockedPRFileDesc {
244 public:
245 explicit LockedPRFileDesc(nsSocketTransport *aSocketTransport)
246 : mSocketTransport(aSocketTransport), mFd(nullptr) {
247 MOZ_ASSERT(aSocketTransport);
249 ~LockedPRFileDesc() = default;
250 bool IsInitialized() { return mFd; }
251 LockedPRFileDesc &operator=(PRFileDesc *aFd) {
252 mSocketTransport->mLock.AssertCurrentThreadOwns();
253 mFd = aFd;
254 return *this;
256 operator PRFileDesc *() {
257 if (mSocketTransport->mAttached) {
258 mSocketTransport->mLock.AssertCurrentThreadOwns();
260 return mFd;
262 bool operator==(PRFileDesc *aFd) {
263 mSocketTransport->mLock.AssertCurrentThreadOwns();
264 return mFd == aFd;
267 private:
268 operator LockedPRFileDesc *() { return nullptr; }
269 // Weak ptr to nsSocketTransport since it owns this class.
270 nsSocketTransport *mSocketTransport;
271 PRFileDesc *mFd;
273 friend class LockedPRFileDesc;
275 //-------------------------------------------------------------------------
276 // these members are "set" at initialization time and are never modified
277 // afterwards. this allows them to be safely accessed from any thread.
278 //-------------------------------------------------------------------------
280 // socket type info:
281 char **mTypes;
282 uint32_t mTypeCount;
283 nsCString mHost;
284 nsCString mProxyHost;
285 nsCString mOriginHost;
286 uint16_t mPort;
287 nsCOMPtr<nsIProxyInfo> mProxyInfo;
288 uint16_t mProxyPort;
289 uint16_t mOriginPort;
290 bool mProxyTransparent;
291 bool mProxyTransparentResolvesHost;
292 bool mHttpsProxy;
293 uint32_t mConnectionFlags;
294 // When we fail to connect using a prefered IP family, we tell the consumer to
295 // reset the IP family preference on the connection entry.
296 bool mResetFamilyPreference;
297 uint32_t mTlsFlags;
298 bool mReuseAddrPort;
300 // The origin attributes are used to create sockets. The first party domain
301 // will eventually be used to isolate OCSP cache and is only non-empty when
302 // "privacy.firstparty.isolate" is enabled. Setting this is the only way to
303 // carry origin attributes down to NSPR layers which are final consumers.
304 // It must be set before the socket transport is built.
305 OriginAttributes mOriginAttributes;
307 uint16_t SocketPort() {
308 return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort;
310 const nsCString &SocketHost() {
311 return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost;
314 //-------------------------------------------------------------------------
315 // members accessible only on the socket transport thread:
316 // (the exception being initialization/shutdown time)
317 //-------------------------------------------------------------------------
319 // socket state vars:
320 uint32_t mState; // STATE_??? flags
321 bool mAttached;
322 bool mInputClosed;
323 bool mOutputClosed;
325 // this flag is used to determine if the results of a host lookup arrive
326 // recursively or not. this flag is not protected by any lock.
327 bool mResolving;
329 nsCOMPtr<nsICancelable> mDNSRequest;
330 nsCOMPtr<nsIDNSRecord> mDNSRecord;
332 nsresult mDNSLookupStatus;
333 PRIntervalTime mDNSARequestFinished;
334 nsCOMPtr<nsICancelable> mDNSTxtRequest;
335 nsCString mDNSRecordTxt;
336 bool mEsniQueried;
337 bool mEsniUsed;
339 // mNetAddr/mSelfAddr is valid from GetPeerAddr()/GetSelfAddr() once we have
340 // reached STATE_TRANSFERRING. It must not change after that.
341 void SetSocketName(PRFileDesc *fd);
342 NetAddr mNetAddr;
343 NetAddr mSelfAddr; // getsockname()
344 Atomic<bool, Relaxed> mNetAddrIsSet;
345 Atomic<bool, Relaxed> mSelfAddrIsSet;
347 nsAutoPtr<NetAddr> mBindAddr;
349 // socket methods (these can only be called on the socket thread):
351 void SendStatus(nsresult status);
352 nsresult ResolveHost();
353 nsresult BuildSocket(PRFileDesc *&, bool &, bool &);
354 nsresult InitiateSocket();
355 bool RecoverFromError();
357 void OnMsgInputPending() {
358 if (mState == STATE_TRANSFERRING)
359 mPollFlags |= (PR_POLL_READ | PR_POLL_EXCEPT);
361 void OnMsgOutputPending() {
362 if (mState == STATE_TRANSFERRING)
363 mPollFlags |= (PR_POLL_WRITE | PR_POLL_EXCEPT);
365 void OnMsgInputClosed(nsresult reason);
366 void OnMsgOutputClosed(nsresult reason);
368 // called when the socket is connected
369 void OnSocketConnected();
371 //-------------------------------------------------------------------------
372 // socket input/output objects. these may be accessed on any thread with
373 // the exception of some specific methods (XXX).
375 Mutex mLock; // protects members in this section.
376 LockedPRFileDesc mFD;
377 nsrefcnt mFDref; // mFD is closed when mFDref goes to zero.
378 bool mFDconnected; // mFD is available to consumer when TRUE.
379 bool mFDFastOpenInProgress; // Fast Open is in progress, so
380 // socket available for some
381 // operations.
383 // A delete protector reference to gSocketTransportService held for lifetime
384 // of 'this'. Sometimes used interchangably with gSocketTransportService due
385 // to scoping.
386 RefPtr<nsSocketTransportService> mSocketTransportService;
388 nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
389 nsCOMPtr<nsITransportEventSink> mEventSink;
390 nsCOMPtr<nsISupports> mSecInfo;
392 nsSocketInputStream mInput;
393 nsSocketOutputStream mOutput;
395 friend class nsSocketInputStream;
396 friend class nsSocketOutputStream;
398 // socket timeouts are not protected by any lock.
399 uint16_t mTimeouts[2];
401 // linger options to use when closing
402 bool mLingerPolarity;
403 int16_t mLingerTimeout;
405 // QoS setting for socket
406 uint8_t mQoSBits;
409 // mFD access methods: called with mLock held.
411 PRFileDesc *GetFD_Locked();
412 PRFileDesc *GetFD_LockedAlsoDuringFastOpen();
413 void ReleaseFD_Locked(PRFileDesc *fd);
414 bool FastOpenInProgress();
417 // stream state changes (called outside mLock):
419 void OnInputClosed(nsresult reason) {
420 // no need to post an event if called on the socket thread
421 if (OnSocketThread())
422 OnMsgInputClosed(reason);
423 else
424 PostEvent(MSG_INPUT_CLOSED, reason);
426 void OnInputPending() {
427 // no need to post an event if called on the socket thread
428 if (OnSocketThread())
429 OnMsgInputPending();
430 else
431 PostEvent(MSG_INPUT_PENDING);
433 void OnOutputClosed(nsresult reason) {
434 // no need to post an event if called on the socket thread
435 if (OnSocketThread())
436 OnMsgOutputClosed(reason); // XXX need to not be inside lock!
437 else
438 PostEvent(MSG_OUTPUT_CLOSED, reason);
440 void OnOutputPending() {
441 // no need to post an event if called on the socket thread
442 if (OnSocketThread())
443 OnMsgOutputPending();
444 else
445 PostEvent(MSG_OUTPUT_PENDING);
448 #ifdef ENABLE_SOCKET_TRACING
449 void TraceInBuf(const char *buf, int32_t n);
450 void TraceOutBuf(const char *buf, int32_t n);
451 #endif
453 // Reads prefs to get default keepalive config.
454 nsresult EnsureKeepaliveValsAreInitialized();
456 // Groups calls to fd.SetKeepaliveEnabled and fd.SetKeepaliveVals.
457 nsresult SetKeepaliveEnabledInternal(bool aEnable);
459 // True if keepalive has been enabled by the socket owner. Note: Keepalive
460 // must also be enabled globally for it to be enabled in TCP.
461 bool mKeepaliveEnabled;
463 // Keepalive config (support varies by platform).
464 int32_t mKeepaliveIdleTimeS;
465 int32_t mKeepaliveRetryIntervalS;
466 int32_t mKeepaliveProbeCount;
468 // A Fast Open callback.
469 TCPFastOpen *mFastOpenCallback;
470 bool mFastOpenLayerHasBufferedData;
471 uint8_t mFastOpenStatus;
472 nsresult mFirstRetryError;
474 bool mDoNotRetryToConnect;
477 } // namespace net
478 } // namespace mozilla
480 #endif // !nsSocketTransport_h__