diff options
Diffstat (limited to 'dom/network/TCPSocket.h')
-rw-r--r-- | dom/network/TCPSocket.h | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/dom/network/TCPSocket.h b/dom/network/TCPSocket.h new file mode 100644 index 000000000..e98c03ca5 --- /dev/null +++ b/dom/network/TCPSocket.h @@ -0,0 +1,267 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_TCPSocket_h +#define mozilla_dom_TCPSocket_h + +#include "mozilla/dom/TCPSocketBinding.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "nsITransport.h" +#include "nsIStreamListener.h" +#include "nsIAsyncInputStream.h" +#include "nsISupportsImpl.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" +#include "nsITCPSocketCallback.h" +#include "js/RootingAPI.h" + +class nsISocketTransport; +class nsIInputStreamPump; +class nsIScriptableInputStream; +class nsIBinaryInputStream; +class nsIMultiplexInputStream; +class nsIAsyncStreamCopier; +class nsIInputStream; +class nsINetworkInfo; + +namespace mozilla { +class ErrorResult; +namespace dom { + +class DOMError; +struct ServerSocketOptions; +class TCPServerSocket; +class TCPSocketChild; +class TCPSocketParent; + +// This interface is only used for legacy navigator.mozTCPSocket API compatibility. +class LegacyMozTCPSocket : public nsISupports +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(LegacyMozTCPSocket) + + explicit LegacyMozTCPSocket(nsPIDOMWindowInner* aWindow); + + already_AddRefed<TCPServerSocket> + Listen(uint16_t aPort, + const ServerSocketOptions& aOptions, + uint16_t aBacklog, + ErrorResult& aRv); + + already_AddRefed<TCPSocket> + Open(const nsAString& aHost, + uint16_t aPort, + const SocketOptions& aOptions, + ErrorResult& aRv); + + bool WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector); + +private: + virtual ~LegacyMozTCPSocket(); + + nsCOMPtr<nsIGlobalObject> mGlobal; +}; + +class TCPSocket final : public DOMEventTargetHelper + , public nsIStreamListener + , public nsITransportEventSink + , public nsIInputStreamCallback + , public nsIObserver + , public nsSupportsWeakReference + , public nsITCPSocketCallback +{ +public: + TCPSocket(nsIGlobalObject* aGlobal, const nsAString& aHost, uint16_t aPort, + bool aSsl, bool aUseArrayBuffers); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TCPSocket, DOMEventTargetHelper) + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITRANSPORTEVENTSINK + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIOBSERVER + NS_DECL_NSITCPSOCKETCALLBACK + + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + static bool ShouldTCPSocketExist(JSContext* aCx, JSObject* aGlobal); + + void GetHost(nsAString& aHost); + uint32_t Port(); + bool Ssl(); + uint64_t BufferedAmount(); + void Suspend(); + void Resume(ErrorResult& aRv); + void Close(); + void CloseImmediately(); + bool Send(JSContext* aCx, const nsACString& aData, ErrorResult& aRv); + bool Send(JSContext* aCx, + const ArrayBuffer& aData, + uint32_t aByteOffset, + const Optional<uint32_t>& aByteLength, + ErrorResult& aRv); + TCPReadyState ReadyState(); + TCPSocketBinaryType BinaryType(); + void UpgradeToSecure(ErrorResult& aRv); + + static already_AddRefed<TCPSocket> + Constructor(const GlobalObject& aGlobal, + const nsAString& aHost, + uint16_t aPort, + const SocketOptions& aOptions, + ErrorResult& aRv); + + // Perform a send operation that's asssociated with a sequence number. Used in + // IPC scenarios to track the number of bytes buffered at any given time. + void SendWithTrackingNumber(const nsACString& aData, + const uint32_t& aTrackingNumber, + ErrorResult& aRv); + void SendWithTrackingNumber(JSContext* aCx, + const ArrayBuffer& aData, + uint32_t aByteOffset, + const Optional<uint32_t>& aByteLength, + const uint32_t& aTrackingNumber, + ErrorResult& aRv); + // Create a TCPSocket object from an existing low-level socket connection. + // Used by the TCPServerSocket implementation when a new connection is accepted. + static already_AddRefed<TCPSocket> + CreateAcceptedSocket(nsIGlobalObject* aGlobal, nsISocketTransport* aTransport, bool aUseArrayBuffers); + // Create a TCPSocket object from an existing child-side IPC actor. + // Used by the TCPServerSocketChild implementation when a new connection is accepted. + static already_AddRefed<TCPSocket> + CreateAcceptedSocket(nsIGlobalObject* aGlobal, TCPSocketChild* aSocketBridge, bool aUseArrayBuffers); + + // Initialize this socket's associated app and browser information. + void SetAppIdAndBrowser(uint32_t aAppId, bool aInBrowser); + // Initialize this socket's associated IPC actor in the parent process. + void SetSocketBridgeParent(TCPSocketParent* aBridgeParent); + + static bool SocketEnabled(); + + IMPL_EVENT_HANDLER(open); + IMPL_EVENT_HANDLER(drain); + IMPL_EVENT_HANDLER(data); + IMPL_EVENT_HANDLER(error); + IMPL_EVENT_HANDLER(close); + + nsresult Init(); + + // Inform this socket that a buffered send() has completed sending. + void NotifyCopyComplete(nsresult aStatus); + + // Initialize this socket from a low-level connection that hasn't connected yet + // (called from RecvOpenBind() in TCPSocketParent). + nsresult InitWithUnconnectedTransport(nsISocketTransport* aTransport); + +private: + ~TCPSocket(); + + // Initialize this socket with an existing IPC actor. + void InitWithSocketChild(TCPSocketChild* aBridge); + // Initialize this socket from an existing low-level connection. + nsresult InitWithTransport(nsISocketTransport* aTransport); + // Initialize the input/output streams for this socket object. + nsresult CreateStream(); + // Initialize the asynchronous read operation from this socket's input stream. + nsresult CreateInputStreamPump(); + // Send the contents of the provided input stream, which is assumed to be the given length + // for reporting and buffering purposes. + bool Send(nsIInputStream* aStream, uint32_t aByteLength); + // Begin an asynchronous copy operation if one is not already in progress. + nsresult EnsureCopying(); + // Enable TLS on this socket. + void ActivateTLS(); + // Dispatch an error event if necessary, then dispatch a "close" event. + nsresult MaybeReportErrorAndCloseIfOpen(nsresult status); +#ifdef MOZ_WIDGET_GONK + // Store and reset any saved network stats for this socket. + void SaveNetworkStats(bool aEnforce); +#endif + + // Helper for FireDataStringEvent/FireDataArrayEvent. + nsresult FireDataEvent(JSContext* aCx, const nsAString& aType, + JS::Handle<JS::Value> aData); + // Helper for Close/CloseImmediately + void CloseHelper(bool waitForUnsentData); + + TCPReadyState mReadyState; + // Whether to use strings or array buffers for the "data" event. + bool mUseArrayBuffers; + nsString mHost; + uint16_t mPort; + // Whether this socket is using a secure transport. + bool mSsl; + + // The associated IPC actor in a child process. + RefPtr<TCPSocketChild> mSocketBridgeChild; + // The associated IPC actor in a parent process. + RefPtr<TCPSocketParent> mSocketBridgeParent; + + // Raw socket streams + nsCOMPtr<nsISocketTransport> mTransport; + nsCOMPtr<nsIInputStream> mSocketInputStream; + nsCOMPtr<nsIOutputStream> mSocketOutputStream; + + // Input stream machinery + nsCOMPtr<nsIInputStreamPump> mInputStreamPump; + nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable; + nsCOMPtr<nsIBinaryInputStream> mInputStreamBinary; + + // Output stream machinery + nsCOMPtr<nsIMultiplexInputStream> mMultiplexStream; + nsCOMPtr<nsIAsyncStreamCopier> mMultiplexStreamCopier; + + // Is there an async copy operation in progress? + bool mAsyncCopierActive; + // True if the buffer is full and a "drain" event is expected by the client. + bool mWaitingForDrain; + + // The id of the window that created this socket. + uint64_t mInnerWindowID; + + // The current number of buffered bytes. Only used in content processes when IPC is enabled. + uint64_t mBufferedAmount; + + // The number of times this socket has had `Suspend` called without a corresponding `Resume`. + uint32_t mSuspendCount; + + // The current sequence number (ie. number of send operations) that have been processed. + // This is used in the IPC scenario by the child process to filter out outdated notifications + // about the amount of buffered data present in the parent process. + uint32_t mTrackingNumber; + + // True if this socket has been upgraded to secure after the initial connection, + // but the actual upgrade is waiting for an in-progress copy operation to complete. + bool mWaitingForStartTLS; + // The buffered data awaiting the TLS upgrade to finish. + nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataAfterStartTLS; + + // The data to be sent while AsyncCopier is still active. + nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataWhileCopierActive; + + bool mObserversActive; + +#ifdef MOZ_WIDGET_GONK + // Number of bytes sent. + uint32_t mTxBytes; + // Number of bytes received. + uint32_t mRxBytes; + // The app that owns this socket. + uint32_t mAppId; + // Was this socket created inside of an isolated browser frame? + bool mInIsolatedMozBrowser; + // The name of the active network used by this socket. + nsCOMPtr<nsINetworkInfo> mActiveNetworkInfo; +#endif +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TCPSocket_h |