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 : #include "mozilla/dom/TCPServerSocketBinding.h"
7 : #include "mozilla/dom/TCPServerSocketEvent.h"
8 : #include "mozilla/dom/TCPSocketBinding.h"
9 : #include "TCPServerSocketParent.h"
10 : #include "TCPServerSocketChild.h"
11 : #include "mozilla/dom/Event.h"
12 : #include "mozilla/ErrorResult.h"
13 : #include "TCPServerSocket.h"
14 : #include "TCPSocket.h"
15 :
16 : using namespace mozilla::dom;
17 :
18 : NS_IMPL_CYCLE_COLLECTION_CLASS(TCPServerSocket)
19 :
20 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(TCPServerSocket,
21 : DOMEventTargetHelper)
22 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
23 :
24 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TCPServerSocket,
25 : DOMEventTargetHelper)
26 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerSocket)
27 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeChild)
28 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeParent)
29 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
30 :
31 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TCPServerSocket,
32 : DOMEventTargetHelper)
33 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerSocket)
34 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeChild)
35 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeParent)
36 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
37 :
38 0 : NS_IMPL_ADDREF_INHERITED(TCPServerSocket, DOMEventTargetHelper)
39 0 : NS_IMPL_RELEASE_INHERITED(TCPServerSocket, DOMEventTargetHelper)
40 :
41 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TCPServerSocket)
42 0 : NS_INTERFACE_MAP_ENTRY(nsIServerSocketListener)
43 0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
44 :
45 0 : TCPServerSocket::TCPServerSocket(nsIGlobalObject* aGlobal, uint16_t aPort,
46 0 : bool aUseArrayBuffers, uint16_t aBacklog)
47 : : DOMEventTargetHelper(aGlobal)
48 : , mPort(aPort)
49 : , mBacklog(aBacklog)
50 0 : , mUseArrayBuffers(aUseArrayBuffers)
51 : {
52 0 : }
53 :
54 0 : TCPServerSocket::~TCPServerSocket()
55 : {
56 0 : }
57 :
58 : nsresult
59 0 : TCPServerSocket::Init()
60 : {
61 0 : if (mServerSocket || mServerBridgeChild) {
62 0 : NS_WARNING("Child TCPServerSocket is already listening.");
63 0 : return NS_ERROR_FAILURE;
64 : }
65 :
66 0 : if (XRE_GetProcessType() == GeckoProcessType_Content) {
67 0 : nsCOMPtr<nsIEventTarget> target;
68 0 : if (nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal()) {
69 0 : target = global->EventTargetFor(TaskCategory::Other);
70 : }
71 : mServerBridgeChild =
72 0 : new TCPServerSocketChild(this, mPort, mBacklog, mUseArrayBuffers, target);
73 0 : return NS_OK;
74 : }
75 :
76 : nsresult rv;
77 0 : mServerSocket = do_CreateInstance("@mozilla.org/network/server-socket;1", &rv);
78 0 : NS_ENSURE_SUCCESS(rv, rv);
79 0 : rv = mServerSocket->Init(mPort, false, mBacklog);
80 0 : NS_ENSURE_SUCCESS(rv, rv);
81 0 : rv = mServerSocket->GetPort(&mPort);
82 0 : NS_ENSURE_SUCCESS(rv, rv);
83 0 : rv = mServerSocket->AsyncListen(this);
84 0 : NS_ENSURE_SUCCESS(rv, rv);
85 0 : return NS_OK;
86 : }
87 :
88 : already_AddRefed<TCPServerSocket>
89 0 : TCPServerSocket::Constructor(const GlobalObject& aGlobal,
90 : uint16_t aPort,
91 : const ServerSocketOptions& aOptions,
92 : uint16_t aBacklog,
93 : mozilla::ErrorResult& aRv)
94 : {
95 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
96 0 : if (!global) {
97 0 : aRv = NS_ERROR_FAILURE;
98 0 : return nullptr;
99 : }
100 0 : bool useArrayBuffers = aOptions.mBinaryType == TCPSocketBinaryType::Arraybuffer;
101 0 : RefPtr<TCPServerSocket> socket = new TCPServerSocket(global, aPort, useArrayBuffers, aBacklog);
102 0 : nsresult rv = socket->Init();
103 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
104 0 : aRv = NS_ERROR_FAILURE;
105 0 : return nullptr;
106 : }
107 0 : return socket.forget();
108 : }
109 :
110 : uint16_t
111 0 : TCPServerSocket::LocalPort()
112 : {
113 0 : return mPort;
114 : }
115 :
116 : void
117 0 : TCPServerSocket::Close()
118 : {
119 0 : if (mServerBridgeChild) {
120 0 : mServerBridgeChild->Close();
121 : }
122 0 : if (mServerSocket) {
123 0 : mServerSocket->Close();
124 : }
125 0 : }
126 :
127 : void
128 0 : TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket)
129 : {
130 0 : TCPServerSocketEventInit init;
131 0 : init.mBubbles = false;
132 0 : init.mCancelable = false;
133 0 : init.mSocket = aSocket;
134 :
135 : RefPtr<TCPServerSocketEvent> event =
136 0 : TCPServerSocketEvent::Constructor(this, aType, init);
137 0 : event->SetTrusted(true);
138 : bool dummy;
139 0 : DispatchEvent(event, &dummy);
140 :
141 0 : if (mServerBridgeParent) {
142 0 : mServerBridgeParent->OnConnect(event);
143 : }
144 0 : }
145 :
146 : NS_IMETHODIMP
147 0 : TCPServerSocket::OnSocketAccepted(nsIServerSocket* aServer, nsISocketTransport* aTransport)
148 : {
149 0 : nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
150 0 : RefPtr<TCPSocket> socket = TCPSocket::CreateAcceptedSocket(global, aTransport, mUseArrayBuffers);
151 0 : if (mServerBridgeParent) {
152 0 : socket->SetAppIdAndBrowser(mServerBridgeParent->GetAppId(),
153 0 : mServerBridgeParent->GetInIsolatedMozBrowser());
154 : }
155 0 : FireEvent(NS_LITERAL_STRING("connect"), socket);
156 0 : return NS_OK;
157 : }
158 :
159 : NS_IMETHODIMP
160 0 : TCPServerSocket::OnStopListening(nsIServerSocket* aServer, nsresult aStatus)
161 : {
162 0 : if (aStatus != NS_BINDING_ABORTED) {
163 0 : RefPtr<Event> event = new Event(GetOwner());
164 0 : event->InitEvent(NS_LITERAL_STRING("error"), false, false);
165 0 : event->SetTrusted(true);
166 : bool dummy;
167 0 : DispatchEvent(event, &dummy);
168 :
169 0 : NS_WARNING("Server socket was closed by unexpected reason.");
170 0 : return NS_ERROR_FAILURE;
171 : }
172 0 : mServerSocket = nullptr;
173 0 : return NS_OK;
174 : }
175 :
176 : nsresult
177 0 : TCPServerSocket::AcceptChildSocket(TCPSocketChild* aSocketChild)
178 : {
179 0 : nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
180 0 : NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
181 0 : RefPtr<TCPSocket> socket = TCPSocket::CreateAcceptedSocket(global, aSocketChild, mUseArrayBuffers);
182 0 : NS_ENSURE_TRUE(socket, NS_ERROR_FAILURE);
183 0 : FireEvent(NS_LITERAL_STRING("connect"), socket);
184 0 : return NS_OK;
185 : }
186 :
187 : void
188 0 : TCPServerSocket::SetServerBridgeParent(TCPServerSocketParent* aBridgeParent)
189 : {
190 0 : mServerBridgeParent = aBridgeParent;
191 0 : }
192 :
193 : JSObject*
194 0 : TCPServerSocket::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
195 : {
196 0 : return TCPServerSocketBinding::Wrap(aCx, this, aGivenProto);
197 : }
|