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 "mozilla/dom/TCPSocketBinding.h" 11 #include "mozilla/dom/TypedArray.h" 12 #include "mozilla/DOMEventTargetHelper.h" 13 #include "nsIProxyInfo.h" 14 #include "nsITransport.h" 15 #include "nsIStreamListener.h" 16 #include "nsIAsyncInputStream.h" 17 #include "nsISupportsImpl.h" 18 #include "nsIObserver.h" 19 #include "nsWeakReference.h" 20 #include "nsITCPSocketCallback.h" 21 #include "nsIProtocolProxyCallback.h" 22 #include "js/RootingAPI.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 GetTransport()96 nsISocketTransport* GetTransport() const { return mTransport.get(); } 97 98 void GetHost(nsAString& aHost); 99 uint32_t Port(); 100 bool Ssl(); BufferedAmount()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(); 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 // Enable TLS on this socket. 170 void ActivateTLS(); 171 // Dispatch an error event if necessary, then dispatch a "close" event. 172 nsresult MaybeReportErrorAndCloseIfOpen(nsresult status); 173 174 // Helper for FireDataStringEvent/FireDataArrayEvent. 175 nsresult FireDataEvent(JSContext* aCx, const nsAString& aType, 176 JS::Handle<JS::Value> aData); 177 // Helper for Close/CloseImmediately 178 void CloseHelper(bool waitForUnsentData); 179 180 nsresult ResolveProxy(); 181 182 TCPReadyState mReadyState; 183 // Whether to use strings or array buffers for the "data" event. 184 bool mUseArrayBuffers; 185 nsString mHost; 186 uint16_t mPort; 187 // Whether this socket is using a secure transport. 188 bool mSsl; 189 190 // The associated IPC actor in a child process. 191 RefPtr<TCPSocketChild> mSocketBridgeChild; 192 // The associated IPC actor in a parent process. 193 RefPtr<TCPSocketParent> mSocketBridgeParent; 194 195 // Raw socket streams 196 nsCOMPtr<nsISocketTransport> mTransport; 197 nsCOMPtr<nsIInputStream> mSocketInputStream; 198 nsCOMPtr<nsIOutputStream> mSocketOutputStream; 199 200 nsCOMPtr<nsICancelable> mProxyRequest; 201 202 // Input stream machinery 203 nsCOMPtr<nsIInputStreamPump> mInputStreamPump; 204 nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable; 205 nsCOMPtr<nsIBinaryInputStream> mInputStreamBinary; 206 207 // Is there an async copy operation in progress? 208 bool mAsyncCopierActive; 209 // True if the buffer is full and a "drain" event is expected by the client. 210 bool mWaitingForDrain; 211 212 // The id of the window that created this socket. 213 uint64_t mInnerWindowID; 214 215 // The current number of buffered bytes. Only used in content processes when 216 // IPC is enabled. 217 uint64_t mBufferedAmount; 218 219 // The number of times this socket has had `Suspend` called without a 220 // corresponding `Resume`. 221 uint32_t mSuspendCount; 222 223 // The current sequence number (ie. number of send operations) that have been 224 // processed. This is used in the IPC scenario by the child process to filter 225 // out outdated notifications about the amount of buffered data present in the 226 // parent process. 227 uint32_t mTrackingNumber; 228 229 // True if this socket has been upgraded to secure after the initial 230 // connection, but the actual upgrade is waiting for an in-progress copy 231 // operation to complete. 232 bool mWaitingForStartTLS; 233 // The buffered data awaiting the TLS upgrade to finish. 234 nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataAfterStartTLS; 235 236 // The data to be sent. 237 nsTArray<nsCOMPtr<nsIInputStream>> mPendingData; 238 239 bool mObserversActive; 240 }; 241 242 } // namespace dom 243 } // namespace mozilla 244 245 #endif // mozilla_dom_TCPSocket_h 246