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