dom/network/src/UDPSocketParent.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial