1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/dns/DNSRequestChild.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,247 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et tw=80 : */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/net/DNSRequestChild.h" 1.11 +#include "mozilla/net/NeckoChild.h" 1.12 +#include "nsIDNSRecord.h" 1.13 +#include "nsHostResolver.h" 1.14 +#include "nsTArray.h" 1.15 +#include "nsNetAddr.h" 1.16 +#include "nsIThread.h" 1.17 +#include "nsThreadUtils.h" 1.18 + 1.19 +using namespace mozilla::ipc; 1.20 + 1.21 +namespace mozilla { 1.22 +namespace net { 1.23 + 1.24 +//----------------------------------------------------------------------------- 1.25 +// ChildDNSRecord: 1.26 +// A simple class to provide nsIDNSRecord on the child 1.27 +//----------------------------------------------------------------------------- 1.28 + 1.29 +class ChildDNSRecord : public nsIDNSRecord 1.30 +{ 1.31 +public: 1.32 + NS_DECL_THREADSAFE_ISUPPORTS 1.33 + NS_DECL_NSIDNSRECORD 1.34 + 1.35 + ChildDNSRecord(const DNSRecord& reply, uint16_t flags); 1.36 + virtual ~ChildDNSRecord(); 1.37 + 1.38 +private: 1.39 + nsCString mCanonicalName; 1.40 + nsTArray<NetAddr> mAddresses; 1.41 + uint32_t mCurrent; // addr iterator 1.42 + uint32_t mLength; // number of addrs 1.43 + uint16_t mFlags; 1.44 +}; 1.45 + 1.46 +NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord) 1.47 + 1.48 +ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags) 1.49 + : mCurrent(0) 1.50 + , mFlags(flags) 1.51 +{ 1.52 + mCanonicalName = reply.canonicalName(); 1.53 + 1.54 + // A shame IPDL gives us no way to grab ownership of array: so copy it. 1.55 + const nsTArray<NetAddr>& addrs = reply.addrs(); 1.56 + uint32_t i = 0; 1.57 + mLength = addrs.Length(); 1.58 + for (; i < mLength; i++) { 1.59 + mAddresses.AppendElement(addrs[i]); 1.60 + } 1.61 +} 1.62 + 1.63 +ChildDNSRecord::~ChildDNSRecord() 1.64 +{ 1.65 +} 1.66 + 1.67 +//----------------------------------------------------------------------------- 1.68 +// ChildDNSRecord::nsIDNSRecord 1.69 +//----------------------------------------------------------------------------- 1.70 + 1.71 +NS_IMETHODIMP 1.72 +ChildDNSRecord::GetCanonicalName(nsACString &result) 1.73 +{ 1.74 + if (!(mFlags & nsHostResolver::RES_CANON_NAME)) { 1.75 + return NS_ERROR_NOT_AVAILABLE; 1.76 + } 1.77 + 1.78 + result = mCanonicalName; 1.79 + return NS_OK; 1.80 +} 1.81 + 1.82 +NS_IMETHODIMP 1.83 +ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr) 1.84 +{ 1.85 + if (mCurrent >= mLength) { 1.86 + return NS_ERROR_NOT_AVAILABLE; 1.87 + } 1.88 + 1.89 + memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr)); 1.90 + 1.91 + // both Ipv4/6 use same bits for port, so safe to just use ipv4's field 1.92 + addr->inet.port = port; 1.93 + 1.94 + return NS_OK; 1.95 +} 1.96 + 1.97 +// shamelessly copied from nsDNSRecord 1.98 +NS_IMETHODIMP 1.99 +ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result) 1.100 +{ 1.101 + NetAddr addr; 1.102 + nsresult rv = GetNextAddr(port, &addr); 1.103 + if (NS_FAILED(rv)) return rv; 1.104 + 1.105 + NS_ADDREF(*result = new nsNetAddr(&addr)); 1.106 + 1.107 + return NS_OK; 1.108 +} 1.109 + 1.110 +// also copied from nsDNSRecord 1.111 +NS_IMETHODIMP 1.112 +ChildDNSRecord::GetNextAddrAsString(nsACString &result) 1.113 +{ 1.114 + NetAddr addr; 1.115 + nsresult rv = GetNextAddr(0, &addr); 1.116 + if (NS_FAILED(rv)) { 1.117 + return rv; 1.118 + } 1.119 + 1.120 + char buf[kIPv6CStrBufSize]; 1.121 + if (NetAddrToString(&addr, buf, sizeof(buf))) { 1.122 + result.Assign(buf); 1.123 + return NS_OK; 1.124 + } 1.125 + NS_ERROR("NetAddrToString failed unexpectedly"); 1.126 + return NS_ERROR_FAILURE; // conversion failed for some reason 1.127 +} 1.128 + 1.129 +NS_IMETHODIMP 1.130 +ChildDNSRecord::HasMore(bool *result) 1.131 +{ 1.132 + *result = mCurrent < mLength; 1.133 + return NS_OK; 1.134 +} 1.135 + 1.136 +NS_IMETHODIMP 1.137 +ChildDNSRecord::Rewind() 1.138 +{ 1.139 + mCurrent = 0; 1.140 + return NS_OK; 1.141 +} 1.142 + 1.143 +NS_IMETHODIMP 1.144 +ChildDNSRecord::ReportUnusable(uint16_t aPort) 1.145 +{ 1.146 + // "We thank you for your feedback" == >/dev/null 1.147 + // TODO: we could send info back to parent. 1.148 + return NS_OK; 1.149 +} 1.150 + 1.151 +//----------------------------------------------------------------------------- 1.152 +// DNSRequestChild 1.153 +//----------------------------------------------------------------------------- 1.154 + 1.155 +DNSRequestChild::DNSRequestChild(const nsCString& aHost, 1.156 + const uint32_t& aFlags, 1.157 + nsIDNSListener *aListener, 1.158 + nsIEventTarget *target) 1.159 + : mListener(aListener) 1.160 + , mTarget(target) 1.161 + , mResultStatus(NS_OK) 1.162 + , mHost(aHost) 1.163 + , mFlags(aFlags) 1.164 +{ 1.165 +} 1.166 + 1.167 +void 1.168 +DNSRequestChild::StartRequest() 1.169 +{ 1.170 + // we can only do IPDL on the main thread 1.171 + if (!NS_IsMainThread()) { 1.172 + NS_DispatchToMainThread( 1.173 + NS_NewRunnableMethod(this, &DNSRequestChild::StartRequest)); 1.174 + return; 1.175 + } 1.176 + 1.177 + // Send request to Parent process. 1.178 + gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags); 1.179 + 1.180 + // IPDL holds a reference until IPDL channel gets destroyed 1.181 + AddIPDLReference(); 1.182 +} 1.183 + 1.184 +void 1.185 +DNSRequestChild::CallOnLookupComplete() 1.186 +{ 1.187 + MOZ_ASSERT(mListener); 1.188 + 1.189 + mListener->OnLookupComplete(this, mResultRecord, mResultStatus); 1.190 +} 1.191 + 1.192 +bool 1.193 +DNSRequestChild::Recv__delete__(const DNSRequestResponse& reply) 1.194 +{ 1.195 + MOZ_ASSERT(mListener); 1.196 + 1.197 + switch (reply.type()) { 1.198 + case DNSRequestResponse::TDNSRecord: { 1.199 + mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags); 1.200 + break; 1.201 + } 1.202 + case DNSRequestResponse::Tnsresult: { 1.203 + mResultStatus = reply.get_nsresult(); 1.204 + break; 1.205 + } 1.206 + default: 1.207 + NS_NOTREACHED("unknown type"); 1.208 + return false; 1.209 + } 1.210 + 1.211 + MOZ_ASSERT(NS_IsMainThread()); 1.212 + 1.213 + bool targetIsMain = false; 1.214 + if (!mTarget) { 1.215 + targetIsMain = true; 1.216 + } else { 1.217 + mTarget->IsOnCurrentThread(&targetIsMain); 1.218 + } 1.219 + 1.220 + if (targetIsMain) { 1.221 + CallOnLookupComplete(); 1.222 + } else { 1.223 + nsCOMPtr<nsIRunnable> event = 1.224 + NS_NewRunnableMethod(this, &DNSRequestChild::CallOnLookupComplete); 1.225 + mTarget->Dispatch(event, NS_DISPATCH_NORMAL); 1.226 + } 1.227 + 1.228 + return true; 1.229 +} 1.230 + 1.231 +//----------------------------------------------------------------------------- 1.232 +// DNSRequestChild::nsISupports 1.233 +//----------------------------------------------------------------------------- 1.234 + 1.235 +NS_IMPL_ISUPPORTS(DNSRequestChild, 1.236 + nsICancelable) 1.237 + 1.238 +//----------------------------------------------------------------------------- 1.239 +// DNSRequestChild::nsICancelable 1.240 +//----------------------------------------------------------------------------- 1.241 + 1.242 +NS_IMETHODIMP 1.243 +DNSRequestChild::Cancel(nsresult reason) 1.244 +{ 1.245 + // for now Cancel is a no-op 1.246 + return NS_OK; 1.247 +} 1.248 + 1.249 +//------------------------------------------------------------------------------ 1.250 +}} // mozilla::net