Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 "nsIServiceManager.h"
8 #include "UDPSocketParent.h"
9 #include "nsComponentManagerUtils.h"
10 #include "nsIUDPSocket.h"
11 #include "nsINetAddr.h"
12 #include "mozilla/unused.h"
13 #include "mozilla/net/DNS.h"
15 namespace mozilla {
16 namespace dom {
18 static void
19 FireInternalError(mozilla::net::PUDPSocketParent *aActor, uint32_t aLineNo)
20 {
21 mozilla::unused <<
22 aActor->SendCallback(NS_LITERAL_CSTRING("onerror"),
23 UDPError(NS_LITERAL_CSTRING("Internal error"),
24 NS_LITERAL_CSTRING(__FILE__), aLineNo, 0),
25 NS_LITERAL_CSTRING("connecting"));
26 }
28 static nsresult
29 ConvertNetAddrToString(mozilla::net::NetAddr &netAddr, nsACString *address, uint16_t *port)
30 {
31 NS_ENSURE_ARG_POINTER(address);
32 NS_ENSURE_ARG_POINTER(port);
34 *port = 0;
35 uint32_t bufSize = 0;
37 switch(netAddr.raw.family) {
38 case AF_INET:
39 *port = PR_ntohs(netAddr.inet.port);
40 bufSize = mozilla::net::kIPv4CStrBufSize;
41 break;
42 case AF_INET6:
43 *port = PR_ntohs(netAddr.inet6.port);
44 bufSize = mozilla::net::kIPv6CStrBufSize;
45 break;
46 default:
47 //impossible
48 MOZ_ASSERT(false, "Unexpected address family");
49 return NS_ERROR_INVALID_ARG;
50 }
52 address->SetCapacity(bufSize);
53 NetAddrToString(&netAddr, address->BeginWriting(), bufSize);
54 address->SetLength(strlen(address->BeginReading()));
56 return NS_OK;
57 }
59 NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener)
61 UDPSocketParent::~UDPSocketParent()
62 {
63 }
65 // PUDPSocketParent methods
67 bool
68 UDPSocketParent::Init(const nsCString &aHost, const uint16_t aPort)
69 {
70 nsresult rv;
71 NS_ASSERTION(mFilter, "No packet filter");
73 nsCOMPtr<nsIUDPSocket> sock =
74 do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
75 if (NS_FAILED(rv)) {
76 FireInternalError(this, __LINE__);
77 return true;
78 }
80 if (aHost.IsEmpty()) {
81 rv = sock->Init(aPort, false);
82 } else {
83 PRNetAddr prAddr;
84 PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr);
85 PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr);
86 if (status != PR_SUCCESS) {
87 FireInternalError(this, __LINE__);
88 return true;
89 }
91 mozilla::net::NetAddr addr;
92 PRNetAddrToNetAddr(&prAddr, &addr);
93 rv = sock->InitWithAddress(&addr);
94 }
96 if (NS_FAILED(rv)) {
97 FireInternalError(this, __LINE__);
98 return true;
99 }
101 mSocket = sock;
103 net::NetAddr localAddr;
104 mSocket->GetAddress(&localAddr);
106 uint16_t port;
107 nsCString addr;
108 rv = ConvertNetAddrToString(localAddr, &addr, &port);
110 if (NS_FAILED(rv)) {
111 FireInternalError(this, __LINE__);
112 return true;
113 }
115 // register listener
116 mSocket->AsyncListen(this);
117 mozilla::unused <<
118 PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onopen"),
119 UDPAddressInfo(addr, port),
120 NS_LITERAL_CSTRING("connected"));
122 return true;
123 }
125 bool
126 UDPSocketParent::RecvData(const InfallibleTArray<uint8_t> &aData,
127 const nsCString& aRemoteAddress,
128 const uint16_t& aPort)
129 {
130 NS_ENSURE_TRUE(mSocket, true);
131 NS_ASSERTION(mFilter, "No packet filter");
132 // TODO, Bug 933102, filter packets that are sent with hostname.
133 // Until then we simply throw away packets that are sent to a hostname.
134 return true;
136 #if 0
137 // Enable this once we have filtering working with hostname delivery.
138 uint32_t count;
139 nsresult rv = mSocket->Send(aRemoteAddress,
140 aPort, aData.Elements(),
141 aData.Length(), &count);
142 mozilla::unused <<
143 PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
144 UDPSendResult(rv),
145 NS_LITERAL_CSTRING("connected"));
146 NS_ENSURE_SUCCESS(rv, true);
147 NS_ENSURE_TRUE(count > 0, true);
148 return true;
149 #endif
150 }
152 bool
153 UDPSocketParent::RecvDataWithAddress(const InfallibleTArray<uint8_t>& aData,
154 const mozilla::net::NetAddr& aAddr)
155 {
156 NS_ENSURE_TRUE(mSocket, true);
157 NS_ASSERTION(mFilter, "No packet filter");
159 uint32_t count;
160 nsresult rv;
161 bool allowed;
162 rv = mFilter->FilterPacket(&aAddr, aData.Elements(),
163 aData.Length(), nsIUDPSocketFilter::SF_OUTGOING,
164 &allowed);
165 // Sending unallowed data, kill content.
166 NS_ENSURE_SUCCESS(rv, false);
167 NS_ENSURE_TRUE(allowed, false);
169 rv = mSocket->SendWithAddress(&aAddr, aData.Elements(),
170 aData.Length(), &count);
171 mozilla::unused <<
172 PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
173 UDPSendResult(rv),
174 NS_LITERAL_CSTRING("connected"));
175 NS_ENSURE_SUCCESS(rv, true);
176 NS_ENSURE_TRUE(count > 0, true);
177 return true;
178 }
180 bool
181 UDPSocketParent::RecvClose()
182 {
183 NS_ENSURE_TRUE(mSocket, true);
184 nsresult rv = mSocket->Close();
185 mSocket = nullptr;
186 NS_ENSURE_SUCCESS(rv, true);
187 return true;
188 }
190 bool
191 UDPSocketParent::RecvRequestDelete()
192 {
193 mozilla::unused << Send__delete__(this);
194 return true;
195 }
197 void
198 UDPSocketParent::ActorDestroy(ActorDestroyReason why)
199 {
200 MOZ_ASSERT(mIPCOpen);
201 mIPCOpen = false;
202 if (mSocket) {
203 mSocket->Close();
204 }
205 mSocket = nullptr;
206 }
208 // nsIUDPSocketListener
210 NS_IMETHODIMP
211 UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage)
212 {
213 // receiving packet from remote host, forward the message content to child process
214 if (!mIPCOpen) {
215 return NS_OK;
216 }
217 NS_ASSERTION(mFilter, "No packet filter");
219 uint16_t port;
220 nsCString ip;
221 nsCOMPtr<nsINetAddr> fromAddr;
222 aMessage->GetFromAddr(getter_AddRefs(fromAddr));
223 fromAddr->GetPort(&port);
224 fromAddr->GetAddress(ip);
226 nsCString data;
227 aMessage->GetData(data);
229 const char* buffer = data.get();
230 uint32_t len = data.Length();
232 bool allowed;
233 mozilla::net::NetAddr addr;
234 fromAddr->GetNetAddr(&addr);
235 nsresult rv = mFilter->FilterPacket(&addr,
236 (const uint8_t*)buffer, len,
237 nsIUDPSocketFilter::SF_INCOMING,
238 &allowed);
239 // Receiving unallowed data, drop.
240 NS_ENSURE_SUCCESS(rv, NS_OK);
241 NS_ENSURE_TRUE(allowed, NS_OK);
243 FallibleTArray<uint8_t> fallibleArray;
244 if (!fallibleArray.InsertElementsAt(0, buffer, len)) {
245 FireInternalError(this, __LINE__);
246 return NS_ERROR_OUT_OF_MEMORY;
247 }
248 InfallibleTArray<uint8_t> infallibleArray;
249 infallibleArray.SwapElements(fallibleArray);
251 // compose callback
252 mozilla::unused <<
253 PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("ondata"),
254 UDPMessage(ip, port, infallibleArray),
255 NS_LITERAL_CSTRING("connected"));
257 return NS_OK;
258 }
260 NS_IMETHODIMP
261 UDPSocketParent::OnStopListening(nsIUDPSocket* aSocket, nsresult aStatus)
262 {
263 // underlying socket is dead, send state update to child process
264 if (mIPCOpen) {
265 mozilla::unused <<
266 PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onclose"),
267 mozilla::void_t(),
268 NS_LITERAL_CSTRING("closed"));
269 }
270 return NS_OK;
271 }
273 } // namespace dom
274 } // namespace mozilla