TCPSocket.h (9124B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_TCPSocket_h 8 #define mozilla_dom_TCPSocket_h 9 10 #include "js/RootingAPI.h" 11 #include "mozilla/DOMEventTargetHelper.h" 12 #include "mozilla/dom/TCPSocketBinding.h" 13 #include "mozilla/dom/TypedArray.h" 14 #include "nsIAsyncInputStream.h" 15 #include "nsIObserver.h" 16 #include "nsIProtocolProxyCallback.h" 17 #include "nsIProxyInfo.h" 18 #include "nsIStreamListener.h" 19 #include "nsISupportsImpl.h" 20 #include "nsITCPSocketCallback.h" 21 #include "nsITransport.h" 22 #include "nsWeakReference.h" 23 24 class nsISocketTransport; 25 class nsIInputStreamPump; 26 class nsIScriptableInputStream; 27 class nsIBinaryInputStream; 28 class nsIMultiplexInputStream; 29 class nsIAsyncStreamCopier; 30 class nsIInputStream; 31 class nsINetworkInfo; 32 33 namespace mozilla { 34 class ErrorResult; 35 namespace dom { 36 37 struct ServerSocketOptions; 38 class TCPServerSocket; 39 class TCPSocketChild; 40 class TCPSocketParent; 41 42 // This interface is only used for legacy navigator.mozTCPSocket API 43 // compatibility. 44 class LegacyMozTCPSocket : public nsISupports { 45 public: 46 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 47 NS_DECL_CYCLE_COLLECTION_CLASS(LegacyMozTCPSocket) 48 49 explicit LegacyMozTCPSocket(nsPIDOMWindowInner* aWindow); 50 51 already_AddRefed<TCPServerSocket> Listen(uint16_t aPort, 52 const ServerSocketOptions& aOptions, 53 uint16_t aBacklog, ErrorResult& aRv); 54 55 already_AddRefed<TCPSocket> Open(const nsAString& aHost, uint16_t aPort, 56 const SocketOptions& aOptions, 57 ErrorResult& aRv); 58 59 bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, 60 JS::MutableHandle<JSObject*> aReflector); 61 62 private: 63 virtual ~LegacyMozTCPSocket(); 64 65 nsCOMPtr<nsIGlobalObject> mGlobal; 66 }; 67 68 class TCPSocket final : public DOMEventTargetHelper, 69 public nsIStreamListener, 70 public nsITransportEventSink, 71 public nsIInputStreamCallback, 72 public nsIObserver, 73 public nsSupportsWeakReference, 74 public nsITCPSocketCallback, 75 public nsIProtocolProxyCallback { 76 public: 77 TCPSocket(nsIGlobalObject* aGlobal, const nsAString& aHost, uint16_t aPort, 78 bool aSsl, bool aUseArrayBuffers); 79 80 NS_DECL_ISUPPORTS_INHERITED 81 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TCPSocket, 82 DOMEventTargetHelper) 83 NS_DECL_NSIREQUESTOBSERVER 84 NS_DECL_NSISTREAMLISTENER 85 NS_DECL_NSITRANSPORTEVENTSINK 86 NS_DECL_NSIINPUTSTREAMCALLBACK 87 NS_DECL_NSIOBSERVER 88 NS_DECL_NSITCPSOCKETCALLBACK 89 NS_DECL_NSIPROTOCOLPROXYCALLBACK 90 91 virtual JSObject* WrapObject(JSContext* aCx, 92 JS::Handle<JSObject*> aGivenProto) override; 93 94 static bool ShouldTCPSocketExist(JSContext* aCx, JSObject* aGlobal); 95 96 nsISocketTransport* GetTransport() const { return mTransport.get(); } 97 98 void GetHost(nsAString& aHost); 99 uint32_t Port() const; 100 bool Ssl() const; 101 uint64_t BufferedAmount() const { return mBufferedAmount; } 102 void Suspend(); 103 void Resume(ErrorResult& aRv); 104 void Close(); 105 void CloseImmediately(); 106 bool Send(const nsACString& aData, ErrorResult& aRv); 107 bool Send(const ArrayBuffer& aData, uint32_t aByteOffset, 108 const Optional<uint32_t>& aByteLength, ErrorResult& aRv); 109 TCPReadyState ReadyState(); 110 TCPSocketBinaryType BinaryType() const; 111 void UpgradeToSecure(ErrorResult& aRv); 112 113 static already_AddRefed<TCPSocket> Constructor(const GlobalObject& aGlobal, 114 const nsAString& aHost, 115 uint16_t aPort, 116 const SocketOptions& aOptions, 117 ErrorResult& aRv); 118 119 // Create a TCPSocket object from an existing low-level socket connection. 120 // Used by the TCPServerSocket implementation when a new connection is 121 // accepted. 122 static already_AddRefed<TCPSocket> CreateAcceptedSocket( 123 nsIGlobalObject* aGlobal, nsISocketTransport* aTransport, 124 bool aUseArrayBuffers); 125 // Create a TCPSocket object from an existing child-side IPC actor. 126 // Used by the TCPServerSocketChild implementation when a new connection is 127 // accepted. 128 static already_AddRefed<TCPSocket> CreateAcceptedSocket( 129 nsIGlobalObject* aGlobal, TCPSocketChild* aBridge, bool aUseArrayBuffers); 130 131 // Initialize this socket's associated IPC actor in the parent process. 132 void SetSocketBridgeParent(TCPSocketParent* aBridgeParent); 133 134 static bool SocketEnabled(); 135 136 IMPL_EVENT_HANDLER(open); 137 IMPL_EVENT_HANDLER(drain); 138 IMPL_EVENT_HANDLER(data); 139 IMPL_EVENT_HANDLER(error); 140 IMPL_EVENT_HANDLER(close); 141 142 nsresult Init(nsIProxyInfo* aProxyInfo); 143 144 // Inform this socket that a buffered send() has completed sending. 145 void NotifyCopyComplete(nsresult aStatus); 146 147 // Initialize this socket from a low-level connection that hasn't connected 148 // yet (called from RecvOpenBind() in TCPSocketParent). 149 nsresult InitWithUnconnectedTransport(nsISocketTransport* aTransport); 150 151 private: 152 ~TCPSocket(); 153 154 // Initialize this socket with an existing IPC actor. 155 void InitWithSocketChild(TCPSocketChild* aSocketBridge); 156 // Initialize this socket from an existing low-level connection. 157 nsresult InitWithTransport(nsISocketTransport* aTransport); 158 // Initialize the input/output streams for this socket object. 159 nsresult CreateStream(); 160 // Initialize the asynchronous read operation from this socket's input stream. 161 nsresult CreateInputStreamPump(); 162 // Send the contents of the provided input stream, which is assumed to be the 163 // given length for reporting and buffering purposes. 164 bool Send(nsIInputStream* aStream, uint32_t aByteLength); 165 // Begin an asynchronous copy operation if one is not already in progress. 166 nsresult EnsureCopying(); 167 // Re-calculate buffered amount. 168 void CalculateBufferedAmount(); 169 // Helper function, should be called by ActivateTLS(), only. 170 void ActivateTLSHelper(); 171 // Enable TLS on this socket, dispatch to STSThread if necessary. 172 void ActivateTLS(); 173 // Dispatch an error event if necessary, then dispatch a "close" event. 174 nsresult MaybeReportErrorAndCloseIfOpen(nsresult status); 175 176 // Helper for FireDataStringEvent/FireDataArrayEvent. 177 nsresult FireDataEvent(JSContext* aCx, const nsAString& aType, 178 JS::Handle<JS::Value> aData); 179 // Helper for Close/CloseImmediately 180 void CloseHelper(bool waitForUnsentData); 181 182 nsresult ResolveProxy(); 183 184 TCPReadyState mReadyState; 185 // Whether to use strings or array buffers for the "data" event. 186 bool mUseArrayBuffers; 187 nsString mHost; 188 uint16_t mPort; 189 // Whether this socket is using a secure transport. 190 bool mSsl; 191 192 // The associated IPC actor in a child process. 193 RefPtr<TCPSocketChild> mSocketBridgeChild; 194 // The associated IPC actor in a parent process. 195 RefPtr<TCPSocketParent> mSocketBridgeParent; 196 197 // Raw socket streams 198 nsCOMPtr<nsISocketTransport> mTransport; 199 nsCOMPtr<nsIInputStream> mSocketInputStream; 200 nsCOMPtr<nsIOutputStream> mSocketOutputStream; 201 202 nsCOMPtr<nsICancelable> mProxyRequest; 203 204 // Input stream machinery 205 nsCOMPtr<nsIInputStreamPump> mInputStreamPump; 206 nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable; 207 nsCOMPtr<nsIBinaryInputStream> mInputStreamBinary; 208 209 // Is there an async copy operation in progress? 210 bool mAsyncCopierActive; 211 // True if the buffer is full and a "drain" event is expected by the client. 212 bool mWaitingForDrain; 213 214 // The id of the window that created this socket. 215 uint64_t mInnerWindowID; 216 217 // The current number of buffered bytes. Only used in content processes when 218 // IPC is enabled. 219 uint64_t mBufferedAmount; 220 221 // The number of times this socket has had `Suspend` called without a 222 // corresponding `Resume`. 223 uint32_t mSuspendCount; 224 225 // The current sequence number (ie. number of send operations) that have been 226 // processed. This is used in the IPC scenario by the child process to filter 227 // out outdated notifications about the amount of buffered data present in the 228 // parent process. 229 uint32_t mTrackingNumber; 230 231 // True if this socket has been upgraded to secure after the initial 232 // connection, but the actual upgrade is waiting for an in-progress copy 233 // operation to complete. 234 bool mWaitingForStartTLS; 235 // The buffered data awaiting the TLS upgrade to finish. 236 nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataAfterStartTLS; 237 238 // The data to be sent. 239 nsTArray<nsCOMPtr<nsIInputStream>> mPendingData; 240 241 bool mObserversActive; 242 }; 243 244 } // namespace dom 245 } // namespace mozilla 246 247 #endif // mozilla_dom_TCPSocket_h