netwerk/base/src/nsSocketTransport2.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial