Wed, 31 Dec 2014 06:55:46 +0100
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