nsSocketTransport2.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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/. */
  4. #ifndef nsSocketTransport2_h__
  5. #define nsSocketTransport2_h__
  6. #ifdef DEBUG_darinf
  7. #define ENABLE_SOCKET_TRACING
  8. #endif
  9. #include "mozilla/Mutex.h"
  10. #include "nsSocketTransportService2.h"
  11. #include "nsString.h"
  12. #include "nsCOMPtr.h"
  13. #include "nsIInterfaceRequestor.h"
  14. #include "nsISocketTransport.h"
  15. #include "nsIAsyncInputStream.h"
  16. #include "nsIAsyncOutputStream.h"
  17. #include "nsIDNSListener.h"
  18. #include "nsIClassInfo.h"
  19. #include "mozilla/net/DNS.h"
  20. #include "nsASocketHandler.h"
  21. #include "prerror.h"
  22. #include "nsAutoPtr.h"
  23. class nsICancelable;
  24. class nsIDNSRecord;
  25. class nsIInterfaceRequestor;
  26. //-----------------------------------------------------------------------------
  27. // after this short interval, we will return to PR_Poll
  28. #define NS_SOCKET_CONNECT_TIMEOUT PR_MillisecondsToInterval(20)
  29. //-----------------------------------------------------------------------------
  30. namespace mozilla {
  31. namespace net {
  32. nsresult
  33. ErrorAccordingToNSPR(PRErrorCode errorCode);
  34. class nsSocketTransport;
  35. class nsSocketInputStream : public nsIAsyncInputStream
  36. {
  37. public:
  38. NS_DECL_ISUPPORTS_INHERITED
  39. NS_DECL_NSIINPUTSTREAM
  40. NS_DECL_NSIASYNCINPUTSTREAM
  41. explicit nsSocketInputStream(nsSocketTransport *);
  42. virtual ~nsSocketInputStream();
  43. bool IsReferenced() { return mReaderRefCnt > 0; }
  44. nsresult Condition() { return mCondition; }
  45. uint64_t ByteCount() { return mByteCount; }
  46. // called by the socket transport on the socket thread...
  47. void OnSocketReady(nsresult condition);
  48. private:
  49. nsSocketTransport *mTransport;
  50. ThreadSafeAutoRefCnt mReaderRefCnt;
  51. // access to these is protected by mTransport->mLock
  52. nsresult mCondition;
  53. nsCOMPtr<nsIInputStreamCallback> mCallback;
  54. uint32_t mCallbackFlags;
  55. uint64_t mByteCount;
  56. };
  57. //-----------------------------------------------------------------------------
  58. class nsSocketOutputStream : public nsIAsyncOutputStream
  59. {
  60. public:
  61. NS_DECL_ISUPPORTS_INHERITED
  62. NS_DECL_NSIOUTPUTSTREAM
  63. NS_DECL_NSIASYNCOUTPUTSTREAM
  64. explicit nsSocketOutputStream(nsSocketTransport *);
  65. virtual ~nsSocketOutputStream();
  66. bool IsReferenced() { return mWriterRefCnt > 0; }
  67. nsresult Condition() { return mCondition; }
  68. uint64_t ByteCount() { return mByteCount; }
  69. // called by the socket transport on the socket thread...
  70. void OnSocketReady(nsresult condition);
  71. private:
  72. static nsresult WriteFromSegments(nsIInputStream *, void *,
  73. const char *, uint32_t offset,
  74. uint32_t count, uint32_t *countRead);
  75. nsSocketTransport *mTransport;
  76. ThreadSafeAutoRefCnt mWriterRefCnt;
  77. // access to these is protected by mTransport->mLock
  78. nsresult mCondition;
  79. nsCOMPtr<nsIOutputStreamCallback> mCallback;
  80. uint32_t mCallbackFlags;
  81. uint64_t mByteCount;
  82. };
  83. //-----------------------------------------------------------------------------
  84. class nsSocketTransport final : public nsASocketHandler
  85. , public nsISocketTransport
  86. , public nsIDNSListener
  87. , public nsIClassInfo
  88. , public nsIInterfaceRequestor
  89. {
  90. public:
  91. NS_DECL_THREADSAFE_ISUPPORTS
  92. NS_DECL_NSITRANSPORT
  93. NS_DECL_NSISOCKETTRANSPORT
  94. NS_DECL_NSIDNSLISTENER
  95. NS_DECL_NSICLASSINFO
  96. NS_DECL_NSIINTERFACEREQUESTOR
  97. nsSocketTransport();
  98. // this method instructs the socket transport to open a socket of the
  99. // given type(s) to the given host or proxy.
  100. nsresult Init(const char **socketTypes, uint32_t typeCount,
  101. const nsACString &host, uint16_t port,
  102. const nsACString &hostRoute, uint16_t portRoute,
  103. nsIProxyInfo *proxyInfo);
  104. // Alternative Init method for when the IP-address of the host
  105. // has been pre-resolved using a alternative means (e.g. FlyWeb service
  106. // info).
  107. nsresult InitPreResolved(const char **socketTypes, uint32_t typeCount,
  108. const nsACString &host, uint16_t port,
  109. const nsACString &hostRoute, uint16_t portRoute,
  110. nsIProxyInfo *proxyInfo,
  111. const mozilla::net::NetAddr* addr);
  112. // this method instructs the socket transport to use an already connected
  113. // socket with the given address.
  114. nsresult InitWithConnectedSocket(PRFileDesc *socketFD,
  115. const NetAddr *addr);
  116. // this method instructs the socket transport to use an already connected
  117. // socket with the given address, and additionally supplies security info.
  118. nsresult InitWithConnectedSocket(PRFileDesc* aSocketFD,
  119. const NetAddr* aAddr,
  120. nsISupports* aSecInfo);
  121. // This method instructs the socket transport to open a socket
  122. // connected to the given Unix domain address. We can only create
  123. // unlayered, simple, stream sockets.
  124. nsresult InitWithFilename(const char *filename);
  125. // nsASocketHandler methods:
  126. void OnSocketReady(PRFileDesc *, int16_t outFlags) override;
  127. void OnSocketDetached(PRFileDesc *) override;
  128. void IsLocal(bool *aIsLocal) override;
  129. void OnKeepaliveEnabledPrefChange(bool aEnabled) override final;
  130. // called when a socket event is handled
  131. void OnSocketEvent(uint32_t type, nsresult status, nsISupports *param);
  132. uint64_t ByteCountReceived() override { return mInput.ByteCount(); }
  133. uint64_t ByteCountSent() override { return mOutput.ByteCount(); }
  134. static void CloseSocket(PRFileDesc *aFd);
  135. protected:
  136. virtual ~nsSocketTransport();
  137. void CleanupTypes();
  138. private:
  139. // event types
  140. enum {
  141. MSG_ENSURE_CONNECT,
  142. MSG_DNS_LOOKUP_COMPLETE,
  143. MSG_RETRY_INIT_SOCKET,
  144. MSG_TIMEOUT_CHANGED,
  145. MSG_INPUT_CLOSED,
  146. MSG_INPUT_PENDING,
  147. MSG_OUTPUT_CLOSED,
  148. MSG_OUTPUT_PENDING
  149. };
  150. nsresult PostEvent(uint32_t type, nsresult status = NS_OK, nsISupports *param = nullptr);
  151. enum {
  152. STATE_CLOSED,
  153. STATE_IDLE,
  154. STATE_RESOLVING,
  155. STATE_CONNECTING,
  156. STATE_TRANSFERRING
  157. };
  158. // Safer way to get and automatically release PRFileDesc objects.
  159. class MOZ_STACK_CLASS PRFileDescAutoLock
  160. {
  161. public:
  162. explicit PRFileDescAutoLock(nsSocketTransport *aSocketTransport,
  163. nsresult *aConditionWhileLocked = nullptr)
  164. : mSocketTransport(aSocketTransport)
  165. , mFd(nullptr)
  166. {
  167. MOZ_ASSERT(aSocketTransport);
  168. MutexAutoLock lock(mSocketTransport->mLock);
  169. if (aConditionWhileLocked) {
  170. *aConditionWhileLocked = mSocketTransport->mCondition;
  171. if (NS_FAILED(mSocketTransport->mCondition)) {
  172. return;
  173. }
  174. }
  175. mFd = mSocketTransport->GetFD_Locked();
  176. }
  177. ~PRFileDescAutoLock() {
  178. MutexAutoLock lock(mSocketTransport->mLock);
  179. if (mFd) {
  180. mSocketTransport->ReleaseFD_Locked(mFd);
  181. }
  182. }
  183. bool IsInitialized() {
  184. return mFd;
  185. }
  186. operator PRFileDesc*() {
  187. return mFd;
  188. }
  189. nsresult SetKeepaliveEnabled(bool aEnable);
  190. nsresult SetKeepaliveVals(bool aEnabled, int aIdleTime,
  191. int aRetryInterval, int aProbeCount);
  192. private:
  193. operator PRFileDescAutoLock*() { return nullptr; }
  194. // Weak ptr to nsSocketTransport since this is a stack class only.
  195. nsSocketTransport *mSocketTransport;
  196. PRFileDesc *mFd;
  197. };
  198. friend class PRFileDescAutoLock;
  199. class LockedPRFileDesc
  200. {
  201. public:
  202. explicit LockedPRFileDesc(nsSocketTransport *aSocketTransport)
  203. : mSocketTransport(aSocketTransport)
  204. , mFd(nullptr)
  205. {
  206. MOZ_ASSERT(aSocketTransport);
  207. }
  208. ~LockedPRFileDesc() {}
  209. bool IsInitialized() {
  210. return mFd;
  211. }
  212. LockedPRFileDesc& operator=(PRFileDesc *aFd) {
  213. mSocketTransport->mLock.AssertCurrentThreadOwns();
  214. mFd = aFd;
  215. return *this;
  216. }
  217. operator PRFileDesc*() {
  218. if (mSocketTransport->mAttached) {
  219. mSocketTransport->mLock.AssertCurrentThreadOwns();
  220. }
  221. return mFd;
  222. }
  223. bool operator==(PRFileDesc *aFd) {
  224. mSocketTransport->mLock.AssertCurrentThreadOwns();
  225. return mFd == aFd;
  226. }
  227. private:
  228. operator LockedPRFileDesc*() { return nullptr; }
  229. // Weak ptr to nsSocketTransport since it owns this class.
  230. nsSocketTransport *mSocketTransport;
  231. PRFileDesc *mFd;
  232. };
  233. friend class LockedPRFileDesc;
  234. //-------------------------------------------------------------------------
  235. // these members are "set" at initialization time and are never modified
  236. // afterwards. this allows them to be safely accessed from any thread.
  237. //-------------------------------------------------------------------------
  238. // socket type info:
  239. char **mTypes;
  240. uint32_t mTypeCount;
  241. nsCString mHost;
  242. nsCString mProxyHost;
  243. nsCString mOriginHost;
  244. uint16_t mPort;
  245. nsCOMPtr<nsIProxyInfo> mProxyInfo;
  246. uint16_t mProxyPort;
  247. uint16_t mOriginPort;
  248. bool mProxyTransparent;
  249. bool mProxyTransparentResolvesHost;
  250. bool mHttpsProxy;
  251. uint32_t mConnectionFlags;
  252. // The origin attributes are used to create sockets. The first party domain
  253. // will eventually be used to isolate OCSP cache and is only non-empty when
  254. // "privacy.firstparty.isolate" is enabled. Setting this is the only way to
  255. // carry origin attributes down to NSPR layers which are final consumers.
  256. // It must be set before the socket transport is built.
  257. NeckoOriginAttributes mOriginAttributes;
  258. uint16_t SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
  259. const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; }
  260. Atomic<bool> mInputClosed{true};
  261. Atomic<bool> mOutputClosed{true};
  262. //-------------------------------------------------------------------------
  263. // members accessible only on the socket transport thread:
  264. // (the exception being initialization/shutdown time)
  265. //-------------------------------------------------------------------------
  266. // socket state vars:
  267. uint32_t mState; // STATE_??? flags
  268. bool mAttached;
  269. // The platform-specific network interface id that this socket
  270. // associated with.
  271. nsCString mNetworkInterfaceId;
  272. // this flag is used to determine if the results of a host lookup arrive
  273. // recursively or not. this flag is not protected by any lock.
  274. bool mResolving;
  275. nsCOMPtr<nsICancelable> mDNSRequest;
  276. nsCOMPtr<nsIDNSRecord> mDNSRecord;
  277. // mNetAddr/mSelfAddr is valid from GetPeerAddr()/GetSelfAddr() once we have
  278. // reached STATE_TRANSFERRING. It must not change after that.
  279. void SetSocketName(PRFileDesc *fd);
  280. NetAddr mNetAddr;
  281. NetAddr mSelfAddr; // getsockname()
  282. Atomic<bool, Relaxed> mNetAddrIsSet;
  283. Atomic<bool, Relaxed> mSelfAddrIsSet;
  284. Atomic<bool, Relaxed> mNetAddrPreResolved;
  285. nsAutoPtr<NetAddr> mBindAddr;
  286. // socket methods (these can only be called on the socket thread):
  287. void SendStatus(nsresult status);
  288. nsresult ResolveHost();
  289. nsresult BuildSocket(PRFileDesc *&, bool &, bool &);
  290. nsresult InitiateSocket();
  291. bool RecoverFromError();
  292. void OnMsgInputPending()
  293. {
  294. if (mState == STATE_TRANSFERRING)
  295. mPollFlags |= (PR_POLL_READ | PR_POLL_EXCEPT);
  296. }
  297. void OnMsgOutputPending()
  298. {
  299. if (mState == STATE_TRANSFERRING)
  300. mPollFlags |= (PR_POLL_WRITE | PR_POLL_EXCEPT);
  301. }
  302. void OnMsgInputClosed(nsresult reason);
  303. void OnMsgOutputClosed(nsresult reason);
  304. // called when the socket is connected
  305. void OnSocketConnected();
  306. //-------------------------------------------------------------------------
  307. // socket input/output objects. these may be accessed on any thread with
  308. // the exception of some specific methods (XXX).
  309. Mutex mLock; // protects members in this section.
  310. LockedPRFileDesc mFD;
  311. nsrefcnt mFDref; // mFD is closed when mFDref goes to zero.
  312. bool mFDconnected; // mFD is available to consumer when TRUE.
  313. // A delete protector reference to gSocketTransportService held for lifetime
  314. // of 'this'. Sometimes used interchangably with gSocketTransportService due
  315. // to scoping.
  316. RefPtr<nsSocketTransportService> mSocketTransportService;
  317. nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
  318. nsCOMPtr<nsITransportEventSink> mEventSink;
  319. nsCOMPtr<nsISupports> mSecInfo;
  320. nsSocketInputStream mInput;
  321. nsSocketOutputStream mOutput;
  322. friend class nsSocketInputStream;
  323. friend class nsSocketOutputStream;
  324. // socket timeouts are not protected by any lock.
  325. uint16_t mTimeouts[2];
  326. // QoS setting for socket
  327. uint8_t mQoSBits;
  328. //
  329. // mFD access methods: called with mLock held.
  330. //
  331. PRFileDesc *GetFD_Locked();
  332. void ReleaseFD_Locked(PRFileDesc *fd);
  333. //
  334. // stream state changes (called outside mLock):
  335. //
  336. void OnInputClosed(nsresult reason)
  337. {
  338. // no need to post an event if called on the socket thread
  339. if (PR_GetCurrentThread() == gSocketThread)
  340. OnMsgInputClosed(reason);
  341. else
  342. PostEvent(MSG_INPUT_CLOSED, reason);
  343. }
  344. void OnInputPending()
  345. {
  346. // no need to post an event if called on the socket thread
  347. if (PR_GetCurrentThread() == gSocketThread)
  348. OnMsgInputPending();
  349. else
  350. PostEvent(MSG_INPUT_PENDING);
  351. }
  352. void OnOutputClosed(nsresult reason)
  353. {
  354. // no need to post an event if called on the socket thread
  355. if (PR_GetCurrentThread() == gSocketThread)
  356. OnMsgOutputClosed(reason); // XXX need to not be inside lock!
  357. else
  358. PostEvent(MSG_OUTPUT_CLOSED, reason);
  359. }
  360. void OnOutputPending()
  361. {
  362. // no need to post an event if called on the socket thread
  363. if (PR_GetCurrentThread() == gSocketThread)
  364. OnMsgOutputPending();
  365. else
  366. PostEvent(MSG_OUTPUT_PENDING);
  367. }
  368. #ifdef ENABLE_SOCKET_TRACING
  369. void TraceInBuf(const char *buf, int32_t n);
  370. void TraceOutBuf(const char *buf, int32_t n);
  371. #endif
  372. // Reads prefs to get default keepalive config.
  373. nsresult EnsureKeepaliveValsAreInitialized();
  374. // Groups calls to fd.SetKeepaliveEnabled and fd.SetKeepaliveVals.
  375. nsresult SetKeepaliveEnabledInternal(bool aEnable);
  376. // True if keepalive has been enabled by the socket owner. Note: Keepalive
  377. // must also be enabled globally for it to be enabled in TCP.
  378. bool mKeepaliveEnabled;
  379. // Keepalive config (support varies by platform).
  380. int32_t mKeepaliveIdleTimeS;
  381. int32_t mKeepaliveRetryIntervalS;
  382. int32_t mKeepaliveProbeCount;
  383. Atomic<bool> mDoNotRetryToConnect{false};
  384. };
  385. } // namespace net
  386. } // namespace mozilla
  387. #endif // !nsSocketTransport_h__