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/. */
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 #include "nsComponentManagerUtils.h"
18 using namespace mozilla::dom
;
20 NS_IMPL_CYCLE_COLLECTION_CLASS(TCPServerSocket
)
22 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(TCPServerSocket
,
24 NS_IMPL_CYCLE_COLLECTION_TRACE_END
26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TCPServerSocket
,
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerSocket
)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeChild
)
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServerBridgeParent
)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TCPServerSocket
,
35 NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerSocket
)
36 NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeChild
)
37 NS_IMPL_CYCLE_COLLECTION_UNLINK(mServerBridgeParent
)
38 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
40 NS_IMPL_ADDREF_INHERITED(TCPServerSocket
, DOMEventTargetHelper
)
41 NS_IMPL_RELEASE_INHERITED(TCPServerSocket
, DOMEventTargetHelper
)
43 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPServerSocket
)
44 NS_INTERFACE_MAP_ENTRY(nsIServerSocketListener
)
45 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
47 TCPServerSocket::TCPServerSocket(nsIGlobalObject
* aGlobal
, uint16_t aPort
,
48 bool aUseArrayBuffers
, uint16_t aBacklog
)
49 : DOMEventTargetHelper(aGlobal
),
52 mUseArrayBuffers(aUseArrayBuffers
) {}
54 TCPServerSocket::~TCPServerSocket() = default;
56 nsresult
TCPServerSocket::Init() {
57 if (mServerSocket
|| mServerBridgeChild
) {
58 NS_WARNING("Child TCPServerSocket is already listening.");
59 return NS_ERROR_FAILURE
;
62 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
64 new TCPServerSocketChild(this, mPort
, mBacklog
, mUseArrayBuffers
);
70 do_CreateInstance("@mozilla.org/network/server-socket;1", &rv
);
71 NS_ENSURE_SUCCESS(rv
, rv
);
72 rv
= mServerSocket
->Init(mPort
, false, mBacklog
);
73 NS_ENSURE_SUCCESS(rv
, rv
);
74 rv
= mServerSocket
->GetPort(&mPort
);
75 NS_ENSURE_SUCCESS(rv
, rv
);
76 rv
= mServerSocket
->AsyncListen(this);
77 NS_ENSURE_SUCCESS(rv
, rv
);
81 already_AddRefed
<TCPServerSocket
> TCPServerSocket::Constructor(
82 const GlobalObject
& aGlobal
, uint16_t aPort
,
83 const ServerSocketOptions
& aOptions
, uint16_t aBacklog
,
84 mozilla::ErrorResult
& aRv
) {
85 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
87 aRv
= NS_ERROR_FAILURE
;
90 bool useArrayBuffers
=
91 aOptions
.mBinaryType
== TCPSocketBinaryType::Arraybuffer
;
92 RefPtr
<TCPServerSocket
> socket
=
93 new TCPServerSocket(global
, aPort
, useArrayBuffers
, aBacklog
);
94 nsresult rv
= socket
->Init();
95 if (NS_WARN_IF(NS_FAILED(rv
))) {
96 aRv
= NS_ERROR_FAILURE
;
99 return socket
.forget();
102 uint16_t TCPServerSocket::LocalPort() const { return mPort
; }
104 void TCPServerSocket::Close() {
105 if (mServerBridgeChild
) {
106 mServerBridgeChild
->Close();
109 mServerSocket
->Close();
113 void TCPServerSocket::FireEvent(const nsAString
& aType
, TCPSocket
* aSocket
) {
114 TCPServerSocketEventInit init
;
115 init
.mBubbles
= false;
116 init
.mCancelable
= false;
117 init
.mSocket
= aSocket
;
119 RefPtr
<TCPServerSocketEvent
> event
=
120 TCPServerSocketEvent::Constructor(this, aType
, init
);
121 event
->SetTrusted(true);
122 DispatchEvent(*event
);
124 if (mServerBridgeParent
) {
125 mServerBridgeParent
->OnConnect(event
);
130 TCPServerSocket::OnSocketAccepted(nsIServerSocket
* aServer
,
131 nsISocketTransport
* aTransport
) {
132 nsCOMPtr
<nsIGlobalObject
> global
= GetOwnerGlobal();
133 RefPtr
<TCPSocket
> socket
=
134 TCPSocket::CreateAcceptedSocket(global
, aTransport
, mUseArrayBuffers
);
135 FireEvent(u
"connect"_ns
, socket
);
140 TCPServerSocket::OnStopListening(nsIServerSocket
* aServer
, nsresult aStatus
) {
141 if (aStatus
!= NS_BINDING_ABORTED
) {
142 RefPtr
<Event
> event
= new Event(GetOwner());
143 event
->InitEvent(u
"error"_ns
, false, false);
144 event
->SetTrusted(true);
145 DispatchEvent(*event
);
147 NS_WARNING("Server socket was closed by unexpected reason.");
148 return NS_ERROR_FAILURE
;
150 mServerSocket
= nullptr;
154 nsresult
TCPServerSocket::AcceptChildSocket(TCPSocketChild
* aSocketChild
) {
155 nsCOMPtr
<nsIGlobalObject
> global
= GetOwnerGlobal();
156 NS_ENSURE_TRUE(global
, NS_ERROR_FAILURE
);
157 RefPtr
<TCPSocket
> socket
=
158 TCPSocket::CreateAcceptedSocket(global
, aSocketChild
, mUseArrayBuffers
);
159 NS_ENSURE_TRUE(socket
, NS_ERROR_FAILURE
);
160 FireEvent(u
"connect"_ns
, socket
);
164 void TCPServerSocket::SetServerBridgeParent(
165 TCPServerSocketParent
* aBridgeParent
) {
166 mServerBridgeParent
= aBridgeParent
;
169 JSObject
* TCPServerSocket::WrapObject(JSContext
* aCx
,
170 JS::Handle
<JSObject
*> aGivenProto
) {
171 return TCPServerSocket_Binding::Wrap(aCx
, this, aGivenProto
);