|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "UDPSocketChild.h" |
|
6 #include "mozilla/net/NeckoChild.h" |
|
7 |
|
8 using mozilla::net::gNeckoChild; |
|
9 |
|
10 namespace mozilla { |
|
11 namespace dom { |
|
12 |
|
13 NS_IMPL_ISUPPORTS(UDPSocketChildBase, nsIUDPSocketChild) |
|
14 |
|
15 UDPSocketChildBase::UDPSocketChildBase() |
|
16 : mIPCOpen(false) |
|
17 { |
|
18 } |
|
19 |
|
20 UDPSocketChildBase::~UDPSocketChildBase() |
|
21 { |
|
22 } |
|
23 |
|
24 void |
|
25 UDPSocketChildBase::ReleaseIPDLReference() |
|
26 { |
|
27 MOZ_ASSERT(mIPCOpen); |
|
28 mIPCOpen = false; |
|
29 this->Release(); |
|
30 } |
|
31 |
|
32 void |
|
33 UDPSocketChildBase::AddIPDLReference() |
|
34 { |
|
35 MOZ_ASSERT(!mIPCOpen); |
|
36 mIPCOpen = true; |
|
37 this->AddRef(); |
|
38 } |
|
39 |
|
40 NS_IMETHODIMP_(MozExternalRefCountType) UDPSocketChild::Release(void) |
|
41 { |
|
42 nsrefcnt refcnt = UDPSocketChildBase::Release(); |
|
43 if (refcnt == 1 && mIPCOpen) { |
|
44 PUDPSocketChild::SendRequestDelete(); |
|
45 return 1; |
|
46 } |
|
47 return refcnt; |
|
48 } |
|
49 |
|
50 UDPSocketChild::UDPSocketChild() |
|
51 :mLocalPort(0) |
|
52 { |
|
53 } |
|
54 |
|
55 UDPSocketChild::~UDPSocketChild() |
|
56 { |
|
57 } |
|
58 |
|
59 // nsIUDPSocketChild Methods |
|
60 |
|
61 NS_IMETHODIMP |
|
62 UDPSocketChild::Bind(nsIUDPSocketInternal *aSocket, |
|
63 const nsACString& aHost, |
|
64 uint16_t aPort) |
|
65 { |
|
66 NS_ENSURE_ARG(aSocket); |
|
67 |
|
68 mSocket = aSocket; |
|
69 AddIPDLReference(); |
|
70 |
|
71 gNeckoChild->SendPUDPSocketConstructor(this, nsCString(aHost), aPort, mFilterName); |
|
72 |
|
73 return NS_OK; |
|
74 } |
|
75 |
|
76 NS_IMETHODIMP |
|
77 UDPSocketChild::Close() |
|
78 { |
|
79 SendClose(); |
|
80 return NS_OK; |
|
81 } |
|
82 |
|
83 NS_IMETHODIMP |
|
84 UDPSocketChild::Send(const nsACString& aHost, |
|
85 uint16_t aPort, |
|
86 const uint8_t *aData, |
|
87 uint32_t aByteLength) |
|
88 { |
|
89 NS_ENSURE_ARG(aData); |
|
90 |
|
91 FallibleTArray<uint8_t> fallibleArray; |
|
92 if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) { |
|
93 return NS_ERROR_OUT_OF_MEMORY; |
|
94 } |
|
95 |
|
96 InfallibleTArray<uint8_t> array; |
|
97 array.SwapElements(fallibleArray); |
|
98 SendData(array, nsCString(aHost), aPort); |
|
99 |
|
100 return NS_OK; |
|
101 } |
|
102 |
|
103 NS_IMETHODIMP |
|
104 UDPSocketChild::SendWithAddr(nsINetAddr *aAddr, |
|
105 const uint8_t *aData, |
|
106 uint32_t aByteLength) |
|
107 { |
|
108 NS_ENSURE_ARG(aAddr); |
|
109 NS_ENSURE_ARG(aData); |
|
110 |
|
111 NetAddr addr; |
|
112 aAddr->GetNetAddr(&addr); |
|
113 |
|
114 return SendWithAddress(&addr, aData, aByteLength); |
|
115 } |
|
116 |
|
117 NS_IMETHODIMP |
|
118 UDPSocketChild::SendWithAddress(const NetAddr *aAddr, |
|
119 const uint8_t *aData, |
|
120 uint32_t aByteLength) |
|
121 { |
|
122 NS_ENSURE_ARG(aAddr); |
|
123 NS_ENSURE_ARG(aData); |
|
124 |
|
125 FallibleTArray<uint8_t> fallibleArray; |
|
126 if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) { |
|
127 return NS_ERROR_OUT_OF_MEMORY; |
|
128 } |
|
129 |
|
130 InfallibleTArray<uint8_t> array; |
|
131 array.SwapElements(fallibleArray); |
|
132 SendDataWithAddress(array, *aAddr); |
|
133 |
|
134 return NS_OK; |
|
135 } |
|
136 |
|
137 NS_IMETHODIMP |
|
138 UDPSocketChild::GetLocalPort(uint16_t *aLocalPort) |
|
139 { |
|
140 NS_ENSURE_ARG_POINTER(aLocalPort); |
|
141 |
|
142 *aLocalPort = mLocalPort; |
|
143 return NS_OK; |
|
144 } |
|
145 |
|
146 NS_IMETHODIMP |
|
147 UDPSocketChild::GetLocalAddress(nsACString &aLocalAddress) |
|
148 { |
|
149 aLocalAddress = mLocalAddress; |
|
150 return NS_OK; |
|
151 } |
|
152 |
|
153 NS_IMETHODIMP |
|
154 UDPSocketChild::SetFilterName(const nsACString &aFilterName) |
|
155 { |
|
156 if (!mFilterName.IsEmpty()) { |
|
157 // filter name can only be set once. |
|
158 return NS_ERROR_FAILURE; |
|
159 } |
|
160 mFilterName = aFilterName; |
|
161 return NS_OK; |
|
162 } |
|
163 |
|
164 NS_IMETHODIMP |
|
165 UDPSocketChild::GetFilterName(nsACString &aFilterName) |
|
166 { |
|
167 aFilterName = mFilterName; |
|
168 return NS_OK; |
|
169 } |
|
170 |
|
171 // PUDPSocketChild Methods |
|
172 bool |
|
173 UDPSocketChild::RecvCallback(const nsCString &aType, |
|
174 const UDPCallbackData &aData, |
|
175 const nsCString &aState) |
|
176 { |
|
177 if (NS_FAILED(mSocket->UpdateReadyState(aState))) |
|
178 NS_ERROR("Shouldn't fail!"); |
|
179 |
|
180 nsresult rv = NS_ERROR_FAILURE; |
|
181 if (aData.type() == UDPCallbackData::Tvoid_t) { |
|
182 rv = mSocket->CallListenerVoid(aType); |
|
183 } else if (aData.type() == UDPCallbackData::TUDPError) { |
|
184 const UDPError& err(aData.get_UDPError()); |
|
185 rv = mSocket->CallListenerError(aType, err.message(), err.filename(), |
|
186 err.lineNumber(), err.columnNumber()); |
|
187 } else if (aData.type() == UDPCallbackData::TUDPMessage) { |
|
188 const UDPMessage& message(aData.get_UDPMessage()); |
|
189 InfallibleTArray<uint8_t> data(message.data()); |
|
190 rv = mSocket->CallListenerReceivedData(aType, message.fromAddr(), message.port(), |
|
191 data.Elements(), data.Length()); |
|
192 } else if (aData.type() == UDPCallbackData::TUDPAddressInfo) { |
|
193 //update local address and port. |
|
194 const UDPAddressInfo& addressInfo(aData.get_UDPAddressInfo()); |
|
195 mLocalAddress = addressInfo.local(); |
|
196 mLocalPort = addressInfo.port(); |
|
197 rv = mSocket->CallListenerVoid(aType); |
|
198 } else if (aData.type() == UDPCallbackData::TUDPSendResult) { |
|
199 const UDPSendResult& returnValue(aData.get_UDPSendResult()); |
|
200 rv = mSocket->CallListenerSent(aType, returnValue.value()); |
|
201 } else { |
|
202 MOZ_ASSERT(false, "Invalid callback type!"); |
|
203 } |
|
204 |
|
205 NS_ENSURE_SUCCESS(rv, true); |
|
206 |
|
207 return true; |
|
208 } |
|
209 |
|
210 } // namespace dom |
|
211 } // namespace mozilla |