netwerk/dns/DNSRequestChild.cpp

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et 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
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/net/DNSRequestChild.h"
     8 #include "mozilla/net/NeckoChild.h"
     9 #include "nsIDNSRecord.h"
    10 #include "nsHostResolver.h"
    11 #include "nsTArray.h"
    12 #include "nsNetAddr.h"
    13 #include "nsIThread.h"
    14 #include "nsThreadUtils.h"
    16 using namespace mozilla::ipc;
    18 namespace mozilla {
    19 namespace net {
    21 //-----------------------------------------------------------------------------
    22 // ChildDNSRecord:
    23 // A simple class to provide nsIDNSRecord on the child
    24 //-----------------------------------------------------------------------------
    26 class ChildDNSRecord : public nsIDNSRecord
    27 {
    28 public:
    29   NS_DECL_THREADSAFE_ISUPPORTS
    30   NS_DECL_NSIDNSRECORD
    32   ChildDNSRecord(const DNSRecord& reply, uint16_t flags);
    33   virtual ~ChildDNSRecord();
    35 private:
    36   nsCString mCanonicalName;
    37   nsTArray<NetAddr> mAddresses;
    38   uint32_t mCurrent; // addr iterator
    39   uint32_t mLength;  // number of addrs
    40   uint16_t mFlags;
    41 };
    43 NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord)
    45 ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
    46   : mCurrent(0)
    47   , mFlags(flags)
    48 {
    49   mCanonicalName = reply.canonicalName();
    51   // A shame IPDL gives us no way to grab ownership of array: so copy it.
    52   const nsTArray<NetAddr>& addrs = reply.addrs();
    53   uint32_t i = 0;
    54   mLength = addrs.Length();
    55   for (; i < mLength; i++) {
    56     mAddresses.AppendElement(addrs[i]);
    57   }
    58 }
    60 ChildDNSRecord::~ChildDNSRecord()
    61 {
    62 }
    64 //-----------------------------------------------------------------------------
    65 // ChildDNSRecord::nsIDNSRecord
    66 //-----------------------------------------------------------------------------
    68 NS_IMETHODIMP
    69 ChildDNSRecord::GetCanonicalName(nsACString &result)
    70 {
    71   if (!(mFlags & nsHostResolver::RES_CANON_NAME)) {
    72     return NS_ERROR_NOT_AVAILABLE;
    73   }
    75   result = mCanonicalName;
    76   return NS_OK;
    77 }
    79 NS_IMETHODIMP
    80 ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
    81 {
    82   if (mCurrent >= mLength) {
    83     return NS_ERROR_NOT_AVAILABLE;
    84   }
    86   memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr));
    88   // both Ipv4/6 use same bits for port, so safe to just use ipv4's field
    89   addr->inet.port = port;
    91   return NS_OK;
    92 }
    94 // shamelessly copied from nsDNSRecord
    95 NS_IMETHODIMP
    96 ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result)
    97 {
    98   NetAddr addr;
    99   nsresult rv = GetNextAddr(port, &addr);
   100   if (NS_FAILED(rv)) return rv;
   102   NS_ADDREF(*result = new nsNetAddr(&addr));
   104   return NS_OK;
   105 }
   107 // also copied from nsDNSRecord
   108 NS_IMETHODIMP
   109 ChildDNSRecord::GetNextAddrAsString(nsACString &result)
   110 {
   111   NetAddr addr;
   112   nsresult rv = GetNextAddr(0, &addr);
   113   if (NS_FAILED(rv)) {
   114     return rv;
   115   }
   117   char buf[kIPv6CStrBufSize];
   118   if (NetAddrToString(&addr, buf, sizeof(buf))) {
   119     result.Assign(buf);
   120     return NS_OK;
   121   }
   122   NS_ERROR("NetAddrToString failed unexpectedly");
   123   return NS_ERROR_FAILURE; // conversion failed for some reason
   124 }
   126 NS_IMETHODIMP
   127 ChildDNSRecord::HasMore(bool *result)
   128 {
   129   *result = mCurrent < mLength;
   130   return NS_OK;
   131 }
   133 NS_IMETHODIMP
   134 ChildDNSRecord::Rewind()
   135 {
   136   mCurrent = 0;
   137   return NS_OK;
   138 }
   140 NS_IMETHODIMP
   141 ChildDNSRecord::ReportUnusable(uint16_t aPort)
   142 {
   143   // "We thank you for your feedback" == >/dev/null
   144   // TODO: we could send info back to parent.
   145   return NS_OK;
   146 }
   148 //-----------------------------------------------------------------------------
   149 // DNSRequestChild
   150 //-----------------------------------------------------------------------------
   152 DNSRequestChild::DNSRequestChild(const nsCString& aHost,
   153                                  const uint32_t& aFlags,
   154                                  nsIDNSListener *aListener,
   155                                  nsIEventTarget *target)
   156   : mListener(aListener)
   157   , mTarget(target)
   158   , mResultStatus(NS_OK)
   159   , mHost(aHost)
   160   , mFlags(aFlags)
   161 {
   162 }
   164 void
   165 DNSRequestChild::StartRequest()
   166 {
   167   // we can only do IPDL on the main thread
   168   if (!NS_IsMainThread()) {
   169     NS_DispatchToMainThread(
   170       NS_NewRunnableMethod(this, &DNSRequestChild::StartRequest));
   171     return;
   172   }
   174   // Send request to Parent process.
   175   gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags);
   177   // IPDL holds a reference until IPDL channel gets destroyed
   178   AddIPDLReference();
   179 }
   181 void
   182 DNSRequestChild::CallOnLookupComplete()
   183 {
   184   MOZ_ASSERT(mListener);
   186   mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
   187 }
   189 bool
   190 DNSRequestChild::Recv__delete__(const DNSRequestResponse& reply)
   191 {
   192   MOZ_ASSERT(mListener);
   194   switch (reply.type()) {
   195   case DNSRequestResponse::TDNSRecord: {
   196     mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
   197     break;
   198   }
   199   case DNSRequestResponse::Tnsresult: {
   200     mResultStatus = reply.get_nsresult();
   201     break;
   202   }
   203   default:
   204     NS_NOTREACHED("unknown type");
   205     return false;
   206   }
   208   MOZ_ASSERT(NS_IsMainThread());
   210   bool targetIsMain = false;
   211   if (!mTarget) {
   212     targetIsMain = true;
   213   } else {
   214     mTarget->IsOnCurrentThread(&targetIsMain);
   215   }
   217   if (targetIsMain) {
   218     CallOnLookupComplete();
   219   } else {
   220     nsCOMPtr<nsIRunnable> event =
   221       NS_NewRunnableMethod(this, &DNSRequestChild::CallOnLookupComplete);
   222     mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
   223   }
   225   return true;
   226 }
   228 //-----------------------------------------------------------------------------
   229 // DNSRequestChild::nsISupports
   230 //-----------------------------------------------------------------------------
   232 NS_IMPL_ISUPPORTS(DNSRequestChild,
   233                   nsICancelable)
   235 //-----------------------------------------------------------------------------
   236 // DNSRequestChild::nsICancelable
   237 //-----------------------------------------------------------------------------
   239 NS_IMETHODIMP
   240 DNSRequestChild::Cancel(nsresult reason)
   241 {
   242   // for now Cancel is a no-op
   243   return NS_OK;
   244 }
   246 //------------------------------------------------------------------------------
   247 }} // mozilla::net

mercurial