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