123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "mozilla/net/ChildDNSService.h"
- #include "mozilla/net/DNSRequestChild.h"
- #include "mozilla/net/NeckoChild.h"
- #include "mozilla/Unused.h"
- #include "nsIDNSRecord.h"
- #include "nsHostResolver.h"
- #include "nsTArray.h"
- #include "nsNetAddr.h"
- #include "nsIThread.h"
- #include "nsThreadUtils.h"
- using namespace mozilla::ipc;
- namespace mozilla {
- namespace net {
- //-----------------------------------------------------------------------------
- // ChildDNSRecord:
- // A simple class to provide nsIDNSRecord on the child
- //-----------------------------------------------------------------------------
- class ChildDNSRecord : public nsIDNSRecord
- {
- public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIDNSRECORD
- ChildDNSRecord(const DNSRecord& reply, uint16_t flags);
- private:
- virtual ~ChildDNSRecord();
- nsCString mCanonicalName;
- nsTArray<NetAddr> mAddresses;
- uint32_t mCurrent; // addr iterator
- uint32_t mLength; // number of addrs
- uint16_t mFlags;
- };
- NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord)
- ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
- : mCurrent(0)
- , mFlags(flags)
- {
- mCanonicalName = reply.canonicalName();
- // A shame IPDL gives us no way to grab ownership of array: so copy it.
- const nsTArray<NetAddr>& addrs = reply.addrs();
- uint32_t i = 0;
- mLength = addrs.Length();
- for (; i < mLength; i++) {
- mAddresses.AppendElement(addrs[i]);
- }
- }
- ChildDNSRecord::~ChildDNSRecord()
- {
- }
- //-----------------------------------------------------------------------------
- // ChildDNSRecord::nsIDNSRecord
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- ChildDNSRecord::GetCanonicalName(nsACString &result)
- {
- if (!(mFlags & nsHostResolver::RES_CANON_NAME)) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- result = mCanonicalName;
- return NS_OK;
- }
- NS_IMETHODIMP
- ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
- {
- if (mCurrent >= mLength) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr));
- // both Ipv4/6 use same bits for port, so safe to just use ipv4's field
- addr->inet.port = htons(port);
- return NS_OK;
- }
- NS_IMETHODIMP
- ChildDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
- {
- aAddressArray = mAddresses;
- return NS_OK;
- }
- // shamelessly copied from nsDNSRecord
- NS_IMETHODIMP
- ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result)
- {
- NetAddr addr;
- nsresult rv = GetNextAddr(port, &addr);
- if (NS_FAILED(rv)) return rv;
- NS_ADDREF(*result = new nsNetAddr(&addr));
- return NS_OK;
- }
- // also copied from nsDNSRecord
- NS_IMETHODIMP
- ChildDNSRecord::GetNextAddrAsString(nsACString &result)
- {
- NetAddr addr;
- nsresult rv = GetNextAddr(0, &addr);
- if (NS_FAILED(rv)) {
- return rv;
- }
- char buf[kIPv6CStrBufSize];
- if (NetAddrToString(&addr, buf, sizeof(buf))) {
- result.Assign(buf);
- return NS_OK;
- }
- NS_ERROR("NetAddrToString failed unexpectedly");
- return NS_ERROR_FAILURE; // conversion failed for some reason
- }
- NS_IMETHODIMP
- ChildDNSRecord::HasMore(bool *result)
- {
- *result = mCurrent < mLength;
- return NS_OK;
- }
- NS_IMETHODIMP
- ChildDNSRecord::Rewind()
- {
- mCurrent = 0;
- return NS_OK;
- }
- NS_IMETHODIMP
- ChildDNSRecord::ReportUnusable(uint16_t aPort)
- {
- // "We thank you for your feedback" == >/dev/null
- // TODO: we could send info back to parent.
- return NS_OK;
- }
- //-----------------------------------------------------------------------------
- // CancelDNSRequestEvent
- //-----------------------------------------------------------------------------
- class CancelDNSRequestEvent : public Runnable
- {
- public:
- CancelDNSRequestEvent(DNSRequestChild* aDnsReq, nsresult aReason)
- : mDnsRequest(aDnsReq)
- , mReasonForCancel(aReason)
- {}
- NS_IMETHOD Run() override
- {
- if (mDnsRequest->mIPCOpen) {
- // Send request to Parent process.
- mDnsRequest->SendCancelDNSRequest(mDnsRequest->mHost, mDnsRequest->mFlags,
- mDnsRequest->mNetworkInterface,
- mReasonForCancel);
- }
- return NS_OK;
- }
- private:
- RefPtr<DNSRequestChild> mDnsRequest;
- nsresult mReasonForCancel;
- };
- //-----------------------------------------------------------------------------
- // DNSRequestChild
- //-----------------------------------------------------------------------------
- DNSRequestChild::DNSRequestChild(const nsCString& aHost,
- const uint32_t& aFlags,
- const nsCString& aNetworkInterface,
- nsIDNSListener *aListener,
- nsIEventTarget *target)
- : mListener(aListener)
- , mTarget(target)
- , mResultStatus(NS_OK)
- , mHost(aHost)
- , mFlags(aFlags)
- , mNetworkInterface(aNetworkInterface)
- , mIPCOpen(false)
- {
- }
- void
- DNSRequestChild::StartRequest()
- {
- // we can only do IPDL on the main thread
- if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(
- NewRunnableMethod(this, &DNSRequestChild::StartRequest));
- return;
- }
- // Send request to Parent process.
- gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags,
- mNetworkInterface);
- mIPCOpen = true;
- // IPDL holds a reference until IPDL channel gets destroyed
- AddIPDLReference();
- }
- void
- DNSRequestChild::CallOnLookupComplete()
- {
- MOZ_ASSERT(mListener);
- mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
- }
- bool
- DNSRequestChild::RecvLookupCompleted(const DNSRequestResponse& reply)
- {
- mIPCOpen = false;
- MOZ_ASSERT(mListener);
- switch (reply.type()) {
- case DNSRequestResponse::TDNSRecord: {
- mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
- break;
- }
- case DNSRequestResponse::Tnsresult: {
- mResultStatus = reply.get_nsresult();
- break;
- }
- default:
- NS_NOTREACHED("unknown type");
- return false;
- }
- MOZ_ASSERT(NS_IsMainThread());
- bool targetIsMain = false;
- if (!mTarget) {
- targetIsMain = true;
- } else {
- mTarget->IsOnCurrentThread(&targetIsMain);
- }
- if (targetIsMain) {
- CallOnLookupComplete();
- } else {
- nsCOMPtr<nsIRunnable> event =
- NewRunnableMethod(this, &DNSRequestChild::CallOnLookupComplete);
- mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
- }
- Unused << Send__delete__(this);
- return true;
- }
- void
- DNSRequestChild::ReleaseIPDLReference()
- {
- // Request is done or destroyed. Remove it from the hash table.
- RefPtr<ChildDNSService> dnsServiceChild =
- dont_AddRef(ChildDNSService::GetSingleton());
- dnsServiceChild->NotifyRequestDone(this);
- Release();
- }
- void
- DNSRequestChild::ActorDestroy(ActorDestroyReason why)
- {
- mIPCOpen = false;
- }
- //-----------------------------------------------------------------------------
- // DNSRequestChild::nsISupports
- //-----------------------------------------------------------------------------
- NS_IMPL_ISUPPORTS(DNSRequestChild,
- nsICancelable)
- //-----------------------------------------------------------------------------
- // DNSRequestChild::nsICancelable
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- DNSRequestChild::Cancel(nsresult reason)
- {
- if(mIPCOpen) {
- // We can only do IPDL on the main thread
- NS_DispatchToMainThread(
- new CancelDNSRequestEvent(this, reason));
- }
- return NS_OK;
- }
- //------------------------------------------------------------------------------
- } // namespace net
- } // namespace mozilla
|