/src/mozilla-central/netwerk/base/ProxyAutoConfig.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
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/. */ |
6 | | |
7 | | #include "ProxyAutoConfig.h" |
8 | | #include "nsICancelable.h" |
9 | | #include "nsIDNSListener.h" |
10 | | #include "nsIDNSRecord.h" |
11 | | #include "nsIDNSService.h" |
12 | | #include "nsINamed.h" |
13 | | #include "nsThreadUtils.h" |
14 | | #include "nsIConsoleService.h" |
15 | | #include "nsIURLParser.h" |
16 | | #include "nsJSUtils.h" |
17 | | #include "jsfriendapi.h" |
18 | | #include "js/CompilationAndEvaluation.h" |
19 | | #include "prnetdb.h" |
20 | | #include "nsITimer.h" |
21 | | #include "mozilla/net/DNS.h" |
22 | | #include "nsServiceManagerUtils.h" |
23 | | #include "nsNetCID.h" |
24 | | |
25 | | namespace mozilla { |
26 | | namespace net { |
27 | | |
28 | | // These are some global helper symbols the PAC format requires that we provide that |
29 | | // are initialized as part of the global javascript context used for PAC evaluations. |
30 | | // Additionally dnsResolve(host) and myIpAddress() are supplied in the same context |
31 | | // but are implemented as c++ helpers. alert(msg) is similarly defined. |
32 | | |
33 | | static const char *sPacUtils = |
34 | | "function dnsDomainIs(host, domain) {\n" |
35 | | " return (host.length >= domain.length &&\n" |
36 | | " host.substring(host.length - domain.length) == domain);\n" |
37 | | "}\n" |
38 | | "" |
39 | | "function dnsDomainLevels(host) {\n" |
40 | | " return host.split('.').length - 1;\n" |
41 | | "}\n" |
42 | | "" |
43 | | "function isValidIpAddress(ipchars) {\n" |
44 | | " var matches = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(ipchars);\n" |
45 | | " if (matches == null) {\n" |
46 | | " return false;\n" |
47 | | " } else if (matches[1] > 255 || matches[2] > 255 || \n" |
48 | | " matches[3] > 255 || matches[4] > 255) {\n" |
49 | | " return false;\n" |
50 | | " }\n" |
51 | | " return true;\n" |
52 | | "}\n" |
53 | | "" |
54 | | "function convert_addr(ipchars) {\n" |
55 | | " var bytes = ipchars.split('.');\n" |
56 | | " var result = ((bytes[0] & 0xff) << 24) |\n" |
57 | | " ((bytes[1] & 0xff) << 16) |\n" |
58 | | " ((bytes[2] & 0xff) << 8) |\n" |
59 | | " (bytes[3] & 0xff);\n" |
60 | | " return result;\n" |
61 | | "}\n" |
62 | | "" |
63 | | "function isInNet(ipaddr, pattern, maskstr) {\n" |
64 | | " if (!isValidIpAddress(pattern) || !isValidIpAddress(maskstr)) {\n" |
65 | | " return false;\n" |
66 | | " }\n" |
67 | | " if (!isValidIpAddress(ipaddr)) {\n" |
68 | | " ipaddr = dnsResolve(ipaddr);\n" |
69 | | " if (ipaddr == null) {\n" |
70 | | " return false;\n" |
71 | | " }\n" |
72 | | " }\n" |
73 | | " var host = convert_addr(ipaddr);\n" |
74 | | " var pat = convert_addr(pattern);\n" |
75 | | " var mask = convert_addr(maskstr);\n" |
76 | | " return ((host & mask) == (pat & mask));\n" |
77 | | " \n" |
78 | | "}\n" |
79 | | "" |
80 | | "function isPlainHostName(host) {\n" |
81 | | " return (host.search('\\\\.') == -1);\n" |
82 | | "}\n" |
83 | | "" |
84 | | "function isResolvable(host) {\n" |
85 | | " var ip = dnsResolve(host);\n" |
86 | | " return (ip != null);\n" |
87 | | "}\n" |
88 | | "" |
89 | | "function localHostOrDomainIs(host, hostdom) {\n" |
90 | | " return (host == hostdom) ||\n" |
91 | | " (hostdom.lastIndexOf(host + '.', 0) == 0);\n" |
92 | | "}\n" |
93 | | "" |
94 | | "function shExpMatch(url, pattern) {\n" |
95 | | " pattern = pattern.replace(/\\./g, '\\\\.');\n" |
96 | | " pattern = pattern.replace(/\\*/g, '.*');\n" |
97 | | " pattern = pattern.replace(/\\?/g, '.');\n" |
98 | | " var newRe = new RegExp('^'+pattern+'$');\n" |
99 | | " return newRe.test(url);\n" |
100 | | "}\n" |
101 | | "" |
102 | | "var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};\n" |
103 | | "var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};\n" |
104 | | "" |
105 | | "function weekdayRange() {\n" |
106 | | " function getDay(weekday) {\n" |
107 | | " if (weekday in wdays) {\n" |
108 | | " return wdays[weekday];\n" |
109 | | " }\n" |
110 | | " return -1;\n" |
111 | | " }\n" |
112 | | " var date = new Date();\n" |
113 | | " var argc = arguments.length;\n" |
114 | | " var wday;\n" |
115 | | " if (argc < 1)\n" |
116 | | " return false;\n" |
117 | | " if (arguments[argc - 1] == 'GMT') {\n" |
118 | | " argc--;\n" |
119 | | " wday = date.getUTCDay();\n" |
120 | | " } else {\n" |
121 | | " wday = date.getDay();\n" |
122 | | " }\n" |
123 | | " var wd1 = getDay(arguments[0]);\n" |
124 | | " var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\n" |
125 | | " return (wd1 == -1 || wd2 == -1) ? false\n" |
126 | | " : (wd1 <= wd2) ? (wd1 <= wday && wday <= wd2)\n" |
127 | | " : (wd2 >= wday || wday >= wd1);\n" |
128 | | "}\n" |
129 | | "" |
130 | | "function dateRange() {\n" |
131 | | " function getMonth(name) {\n" |
132 | | " if (name in months) {\n" |
133 | | " return months[name];\n" |
134 | | " }\n" |
135 | | " return -1;\n" |
136 | | " }\n" |
137 | | " var date = new Date();\n" |
138 | | " var argc = arguments.length;\n" |
139 | | " if (argc < 1) {\n" |
140 | | " return false;\n" |
141 | | " }\n" |
142 | | " var isGMT = (arguments[argc - 1] == 'GMT');\n" |
143 | | "\n" |
144 | | " if (isGMT) {\n" |
145 | | " argc--;\n" |
146 | | " }\n" |
147 | | " // function will work even without explict handling of this case\n" |
148 | | " if (argc == 1) {\n" |
149 | | " var tmp = parseInt(arguments[0]);\n" |
150 | | " if (isNaN(tmp)) {\n" |
151 | | " return ((isGMT ? date.getUTCMonth() : date.getMonth()) ==\n" |
152 | | " getMonth(arguments[0]));\n" |
153 | | " } else if (tmp < 32) {\n" |
154 | | " return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);\n" |
155 | | " } else { \n" |
156 | | " return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==\n" |
157 | | " tmp);\n" |
158 | | " }\n" |
159 | | " }\n" |
160 | | " var year = date.getFullYear();\n" |
161 | | " var date1, date2;\n" |
162 | | " date1 = new Date(year, 0, 1, 0, 0, 0);\n" |
163 | | " date2 = new Date(year, 11, 31, 23, 59, 59);\n" |
164 | | " var adjustMonth = false;\n" |
165 | | " for (var i = 0; i < (argc >> 1); i++) {\n" |
166 | | " var tmp = parseInt(arguments[i]);\n" |
167 | | " if (isNaN(tmp)) {\n" |
168 | | " var mon = getMonth(arguments[i]);\n" |
169 | | " date1.setMonth(mon);\n" |
170 | | " } else if (tmp < 32) {\n" |
171 | | " adjustMonth = (argc <= 2);\n" |
172 | | " date1.setDate(tmp);\n" |
173 | | " } else {\n" |
174 | | " date1.setFullYear(tmp);\n" |
175 | | " }\n" |
176 | | " }\n" |
177 | | " for (var i = (argc >> 1); i < argc; i++) {\n" |
178 | | " var tmp = parseInt(arguments[i]);\n" |
179 | | " if (isNaN(tmp)) {\n" |
180 | | " var mon = getMonth(arguments[i]);\n" |
181 | | " date2.setMonth(mon);\n" |
182 | | " } else if (tmp < 32) {\n" |
183 | | " date2.setDate(tmp);\n" |
184 | | " } else {\n" |
185 | | " date2.setFullYear(tmp);\n" |
186 | | " }\n" |
187 | | " }\n" |
188 | | " if (adjustMonth) {\n" |
189 | | " date1.setMonth(date.getMonth());\n" |
190 | | " date2.setMonth(date.getMonth());\n" |
191 | | " }\n" |
192 | | " if (isGMT) {\n" |
193 | | " var tmp = date;\n" |
194 | | " tmp.setFullYear(date.getUTCFullYear());\n" |
195 | | " tmp.setMonth(date.getUTCMonth());\n" |
196 | | " tmp.setDate(date.getUTCDate());\n" |
197 | | " tmp.setHours(date.getUTCHours());\n" |
198 | | " tmp.setMinutes(date.getUTCMinutes());\n" |
199 | | " tmp.setSeconds(date.getUTCSeconds());\n" |
200 | | " date = tmp;\n" |
201 | | " }\n" |
202 | | " return (date1 <= date2) ? (date1 <= date) && (date <= date2)\n" |
203 | | " : (date2 >= date) || (date >= date1);\n" |
204 | | "}\n" |
205 | | "" |
206 | | "function timeRange() {\n" |
207 | | " var argc = arguments.length;\n" |
208 | | " var date = new Date();\n" |
209 | | " var isGMT= false;\n" |
210 | | "" |
211 | | " if (argc < 1) {\n" |
212 | | " return false;\n" |
213 | | " }\n" |
214 | | " if (arguments[argc - 1] == 'GMT') {\n" |
215 | | " isGMT = true;\n" |
216 | | " argc--;\n" |
217 | | " }\n" |
218 | | "\n" |
219 | | " var hour = isGMT ? date.getUTCHours() : date.getHours();\n" |
220 | | " var date1, date2;\n" |
221 | | " date1 = new Date();\n" |
222 | | " date2 = new Date();\n" |
223 | | "\n" |
224 | | " if (argc == 1) {\n" |
225 | | " return (hour == arguments[0]);\n" |
226 | | " } else if (argc == 2) {\n" |
227 | | " return ((arguments[0] <= hour) && (hour <= arguments[1]));\n" |
228 | | " } else {\n" |
229 | | " switch (argc) {\n" |
230 | | " case 6:\n" |
231 | | " date1.setSeconds(arguments[2]);\n" |
232 | | " date2.setSeconds(arguments[5]);\n" |
233 | | " case 4:\n" |
234 | | " var middle = argc >> 1;\n" |
235 | | " date1.setHours(arguments[0]);\n" |
236 | | " date1.setMinutes(arguments[1]);\n" |
237 | | " date2.setHours(arguments[middle]);\n" |
238 | | " date2.setMinutes(arguments[middle + 1]);\n" |
239 | | " if (middle == 2) {\n" |
240 | | " date2.setSeconds(59);\n" |
241 | | " }\n" |
242 | | " break;\n" |
243 | | " default:\n" |
244 | | " throw 'timeRange: bad number of arguments'\n" |
245 | | " }\n" |
246 | | " }\n" |
247 | | "\n" |
248 | | " if (isGMT) {\n" |
249 | | " date.setFullYear(date.getUTCFullYear());\n" |
250 | | " date.setMonth(date.getUTCMonth());\n" |
251 | | " date.setDate(date.getUTCDate());\n" |
252 | | " date.setHours(date.getUTCHours());\n" |
253 | | " date.setMinutes(date.getUTCMinutes());\n" |
254 | | " date.setSeconds(date.getUTCSeconds());\n" |
255 | | " }\n" |
256 | | " return (date1 <= date2) ? (date1 <= date) && (date <= date2)\n" |
257 | | " : (date2 >= date) || (date >= date1);\n" |
258 | | "\n" |
259 | | "}\n" |
260 | | ""; |
261 | | |
262 | | // sRunning is defined for the helper functions only while the |
263 | | // Javascript engine is running and the PAC object cannot be deleted |
264 | | // or reset. |
265 | | static uint32_t sRunningIndex = 0xdeadbeef; |
266 | | static ProxyAutoConfig *GetRunning() |
267 | 0 | { |
268 | 0 | MOZ_ASSERT(sRunningIndex != 0xdeadbeef); |
269 | 0 | return static_cast<ProxyAutoConfig *>(PR_GetThreadPrivate(sRunningIndex)); |
270 | 0 | } |
271 | | |
272 | | static void SetRunning(ProxyAutoConfig *arg) |
273 | 0 | { |
274 | 0 | MOZ_ASSERT(sRunningIndex != 0xdeadbeef); |
275 | 0 | PR_SetThreadPrivate(sRunningIndex, arg); |
276 | 0 | } |
277 | | |
278 | | // The PACResolver is used for dnsResolve() |
279 | | class PACResolver final : public nsIDNSListener |
280 | | , public nsITimerCallback |
281 | | , public nsINamed |
282 | | { |
283 | | public: |
284 | | NS_DECL_THREADSAFE_ISUPPORTS |
285 | | |
286 | | explicit PACResolver(nsIEventTarget *aTarget) |
287 | | : mStatus(NS_ERROR_FAILURE) |
288 | | , mMainThreadEventTarget(aTarget) |
289 | 0 | { |
290 | 0 | } |
291 | | |
292 | | // nsIDNSListener |
293 | | NS_IMETHOD OnLookupComplete(nsICancelable *request, |
294 | | nsIDNSRecord *record, |
295 | | nsresult status) override |
296 | 0 | { |
297 | 0 | if (mTimer) { |
298 | 0 | mTimer->Cancel(); |
299 | 0 | mTimer = nullptr; |
300 | 0 | } |
301 | 0 |
|
302 | 0 | mRequest = nullptr; |
303 | 0 | mStatus = status; |
304 | 0 | mResponse = record; |
305 | 0 | return NS_OK; |
306 | 0 | } |
307 | | |
308 | | NS_IMETHOD OnLookupByTypeComplete(nsICancelable *request, |
309 | | nsIDNSByTypeRecord *res, |
310 | | nsresult status) override |
311 | 0 | { |
312 | 0 | return NS_OK; |
313 | 0 | } |
314 | | |
315 | | // nsITimerCallback |
316 | | NS_IMETHOD Notify(nsITimer *timer) override |
317 | 0 | { |
318 | 0 | nsCOMPtr<nsICancelable> request(mRequest); |
319 | 0 | if (request) |
320 | 0 | request->Cancel(NS_ERROR_NET_TIMEOUT); |
321 | 0 | mTimer = nullptr; |
322 | 0 | return NS_OK; |
323 | 0 | } |
324 | | |
325 | | // nsINamed |
326 | | NS_IMETHOD GetName(nsACString& aName) override |
327 | 0 | { |
328 | 0 | aName.AssignLiteral("PACResolver"); |
329 | 0 | return NS_OK; |
330 | 0 | } |
331 | | |
332 | | nsresult mStatus; |
333 | | nsCOMPtr<nsICancelable> mRequest; |
334 | | nsCOMPtr<nsIDNSRecord> mResponse; |
335 | | nsCOMPtr<nsITimer> mTimer; |
336 | | nsCOMPtr<nsIEventTarget> mMainThreadEventTarget; |
337 | | |
338 | | private: |
339 | 0 | ~PACResolver() = default; |
340 | | }; |
341 | | NS_IMPL_ISUPPORTS(PACResolver, nsIDNSListener, nsITimerCallback, nsINamed) |
342 | | |
343 | | static |
344 | | void PACLogToConsole(nsString &aMessage) |
345 | 0 | { |
346 | 0 | nsCOMPtr<nsIConsoleService> consoleService = |
347 | 0 | do_GetService(NS_CONSOLESERVICE_CONTRACTID); |
348 | 0 | if (!consoleService) |
349 | 0 | return; |
350 | 0 | |
351 | 0 | consoleService->LogStringMessage(aMessage.get()); |
352 | 0 | } |
353 | | |
354 | | // Javascript errors and warnings are logged to the main error console |
355 | | static void |
356 | | PACLogErrorOrWarning(const nsAString& aKind, JSErrorReport* aReport) |
357 | 0 | { |
358 | 0 | nsString formattedMessage(NS_LITERAL_STRING("PAC Execution ")); |
359 | 0 | formattedMessage += aKind; |
360 | 0 | formattedMessage += NS_LITERAL_STRING(": "); |
361 | 0 | if (aReport->message()) |
362 | 0 | formattedMessage.Append(NS_ConvertUTF8toUTF16(aReport->message().c_str())); |
363 | 0 | formattedMessage += NS_LITERAL_STRING(" ["); |
364 | 0 | formattedMessage.Append(aReport->linebuf(), aReport->linebufLength()); |
365 | 0 | formattedMessage += NS_LITERAL_STRING("]"); |
366 | 0 | PACLogToConsole(formattedMessage); |
367 | 0 | } |
368 | | |
369 | | static void |
370 | | PACWarningReporter(JSContext* aCx, JSErrorReport* aReport) |
371 | 0 | { |
372 | 0 | MOZ_ASSERT(aReport); |
373 | 0 | MOZ_ASSERT(JSREPORT_IS_WARNING(aReport->flags)); |
374 | 0 |
|
375 | 0 | PACLogErrorOrWarning(NS_LITERAL_STRING("Warning"), aReport); |
376 | 0 | } |
377 | | |
378 | | class MOZ_STACK_CLASS AutoPACErrorReporter |
379 | | { |
380 | | JSContext* mCx; |
381 | | |
382 | | public: |
383 | | explicit AutoPACErrorReporter(JSContext* aCx) |
384 | | : mCx(aCx) |
385 | 0 | {} |
386 | 0 | ~AutoPACErrorReporter() { |
387 | 0 | if (!JS_IsExceptionPending(mCx)) { |
388 | 0 | return; |
389 | 0 | } |
390 | 0 | JS::RootedValue exn(mCx); |
391 | 0 | if (!JS_GetPendingException(mCx, &exn)) { |
392 | 0 | return; |
393 | 0 | } |
394 | 0 | JS_ClearPendingException(mCx); |
395 | 0 |
|
396 | 0 | js::ErrorReport report(mCx); |
397 | 0 | if (!report.init(mCx, exn, js::ErrorReport::WithSideEffects)) { |
398 | 0 | JS_ClearPendingException(mCx); |
399 | 0 | return; |
400 | 0 | } |
401 | 0 | |
402 | 0 | PACLogErrorOrWarning(NS_LITERAL_STRING("Error"), report.report()); |
403 | 0 | } |
404 | | }; |
405 | | |
406 | | // timeout of 0 means the normal necko timeout strategy, otherwise the dns request |
407 | | // will be canceled after aTimeout milliseconds |
408 | | static |
409 | | bool PACResolve(const nsCString &aHostName, NetAddr *aNetAddr, |
410 | | unsigned int aTimeout) |
411 | 0 | { |
412 | 0 | if (!GetRunning()) { |
413 | 0 | NS_WARNING("PACResolve without a running ProxyAutoConfig object"); |
414 | 0 | return false; |
415 | 0 | } |
416 | 0 |
|
417 | 0 | return GetRunning()->ResolveAddress(aHostName, aNetAddr, aTimeout); |
418 | 0 | } |
419 | | |
420 | | ProxyAutoConfig::ProxyAutoConfig() |
421 | | : mJSContext(nullptr) |
422 | | , mJSNeedsSetup(false) |
423 | | , mShutdown(true) |
424 | | , mIncludePath(false) |
425 | | , mExtraHeapSize(0) |
426 | 0 | { |
427 | 0 | MOZ_COUNT_CTOR(ProxyAutoConfig); |
428 | 0 | } |
429 | | |
430 | | bool |
431 | | ProxyAutoConfig::ResolveAddress(const nsCString &aHostName, |
432 | | NetAddr *aNetAddr, |
433 | | unsigned int aTimeout) |
434 | 0 | { |
435 | 0 | nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID); |
436 | 0 | if (!dns) |
437 | 0 | return false; |
438 | 0 | |
439 | 0 | RefPtr<PACResolver> helper = new PACResolver(mMainThreadEventTarget); |
440 | 0 | OriginAttributes attrs; |
441 | 0 |
|
442 | 0 | if (NS_FAILED(dns->AsyncResolveNative(aHostName, |
443 | 0 | nsIDNSService::RESOLVE_PRIORITY_MEDIUM, |
444 | 0 | helper, |
445 | 0 | GetCurrentThreadEventTarget(), |
446 | 0 | attrs, |
447 | 0 | getter_AddRefs(helper->mRequest)))) |
448 | 0 | return false; |
449 | 0 | |
450 | 0 | if (aTimeout && helper->mRequest) { |
451 | 0 | if (!mTimer) |
452 | 0 | mTimer = NS_NewTimer(); |
453 | 0 | if (mTimer) { |
454 | 0 | mTimer->SetTarget(mMainThreadEventTarget); |
455 | 0 | mTimer->InitWithCallback(helper, aTimeout, nsITimer::TYPE_ONE_SHOT); |
456 | 0 | helper->mTimer = mTimer; |
457 | 0 | } |
458 | 0 | } |
459 | 0 |
|
460 | 0 | // Spin the event loop of the pac thread until lookup is complete. |
461 | 0 | // nsPACman is responsible for keeping a queue and only allowing |
462 | 0 | // one PAC execution at a time even when it is called re-entrantly. |
463 | 0 | SpinEventLoopUntil([&, helper, this]() { |
464 | 0 | if (!helper->mRequest) { |
465 | 0 | return true; |
466 | 0 | } |
467 | 0 | if (this->mShutdown) { |
468 | 0 | NS_WARNING("mShutdown set with PAC request not cancelled"); |
469 | 0 | MOZ_ASSERT(NS_FAILED(helper->mStatus)); |
470 | 0 | return true; |
471 | 0 | } |
472 | 0 | return false; |
473 | 0 | }); |
474 | 0 |
|
475 | 0 | if (NS_FAILED(helper->mStatus) || |
476 | 0 | NS_FAILED(helper->mResponse->GetNextAddr(0, aNetAddr))) |
477 | 0 | return false; |
478 | 0 | return true; |
479 | 0 | } |
480 | | |
481 | | static |
482 | | bool PACResolveToString(const nsCString &aHostName, |
483 | | nsCString &aDottedDecimal, |
484 | | unsigned int aTimeout) |
485 | 0 | { |
486 | 0 | NetAddr netAddr; |
487 | 0 | if (!PACResolve(aHostName, &netAddr, aTimeout)) |
488 | 0 | return false; |
489 | 0 | |
490 | 0 | char dottedDecimal[128]; |
491 | 0 | if (!NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal))) |
492 | 0 | return false; |
493 | 0 | |
494 | 0 | aDottedDecimal.Assign(dottedDecimal); |
495 | 0 | return true; |
496 | 0 | } |
497 | | |
498 | | // dnsResolve(host) javascript implementation |
499 | | static |
500 | | bool PACDnsResolve(JSContext *cx, unsigned int argc, JS::Value *vp) |
501 | 0 | { |
502 | 0 | JS::CallArgs args = CallArgsFromVp(argc, vp); |
503 | 0 |
|
504 | 0 | if (NS_IsMainThread()) { |
505 | 0 | NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?"); |
506 | 0 | return false; |
507 | 0 | } |
508 | 0 |
|
509 | 0 | if (!args.requireAtLeast(cx, "dnsResolve", 1)) |
510 | 0 | return false; |
511 | 0 | |
512 | 0 | JS::Rooted<JSString*> arg1(cx, JS::ToString(cx, args[0])); |
513 | 0 | if (!arg1) |
514 | 0 | return false; |
515 | 0 | |
516 | 0 | nsAutoJSString hostName; |
517 | 0 | nsAutoCString dottedDecimal; |
518 | 0 |
|
519 | 0 | if (!hostName.init(cx, arg1)) |
520 | 0 | return false; |
521 | 0 | if (PACResolveToString(NS_ConvertUTF16toUTF8(hostName), dottedDecimal, 0)) { |
522 | 0 | JSString *dottedDecimalString = JS_NewStringCopyZ(cx, dottedDecimal.get()); |
523 | 0 | if (!dottedDecimalString) { |
524 | 0 | return false; |
525 | 0 | } |
526 | 0 | |
527 | 0 | args.rval().setString(dottedDecimalString); |
528 | 0 | } |
529 | 0 | else { |
530 | 0 | args.rval().setNull(); |
531 | 0 | } |
532 | 0 |
|
533 | 0 | return true; |
534 | 0 | } |
535 | | |
536 | | // myIpAddress() javascript implementation |
537 | | static |
538 | | bool PACMyIpAddress(JSContext *cx, unsigned int argc, JS::Value *vp) |
539 | 0 | { |
540 | 0 | JS::CallArgs args = JS::CallArgsFromVp(argc, vp); |
541 | 0 |
|
542 | 0 | if (NS_IsMainThread()) { |
543 | 0 | NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?"); |
544 | 0 | return false; |
545 | 0 | } |
546 | 0 |
|
547 | 0 | if (!GetRunning()) { |
548 | 0 | NS_WARNING("PAC myIPAddress without a running ProxyAutoConfig object"); |
549 | 0 | return false; |
550 | 0 | } |
551 | 0 |
|
552 | 0 | return GetRunning()->MyIPAddress(args); |
553 | 0 | } |
554 | | |
555 | | // proxyAlert(msg) javascript implementation |
556 | | static |
557 | | bool PACProxyAlert(JSContext *cx, unsigned int argc, JS::Value *vp) |
558 | 0 | { |
559 | 0 | JS::CallArgs args = CallArgsFromVp(argc, vp); |
560 | 0 |
|
561 | 0 | if (!args.requireAtLeast(cx, "alert", 1)) |
562 | 0 | return false; |
563 | 0 | |
564 | 0 | JS::Rooted<JSString*> arg1(cx, JS::ToString(cx, args[0])); |
565 | 0 | if (!arg1) |
566 | 0 | return false; |
567 | 0 | |
568 | 0 | nsAutoJSString message; |
569 | 0 | if (!message.init(cx, arg1)) |
570 | 0 | return false; |
571 | 0 | |
572 | 0 | nsAutoString alertMessage; |
573 | 0 | alertMessage.SetCapacity(32 + message.Length()); |
574 | 0 | alertMessage += NS_LITERAL_STRING("PAC-alert: "); |
575 | 0 | alertMessage += message; |
576 | 0 | PACLogToConsole(alertMessage); |
577 | 0 |
|
578 | 0 | args.rval().setUndefined(); /* return undefined */ |
579 | 0 | return true; |
580 | 0 | } |
581 | | |
582 | | static const JSFunctionSpec PACGlobalFunctions[] = { |
583 | | JS_FN("dnsResolve", PACDnsResolve, 1, 0), |
584 | | |
585 | | // a global "var pacUseMultihomedDNS = true;" will change behavior |
586 | | // of myIpAddress to actively use DNS |
587 | | JS_FN("myIpAddress", PACMyIpAddress, 0, 0), |
588 | | JS_FN("alert", PACProxyAlert, 1, 0), |
589 | | JS_FS_END |
590 | | }; |
591 | | |
592 | | // JSContextWrapper is a c++ object that manages the context for the JS engine |
593 | | // used on the PAC thread. It is initialized and destroyed on the PAC thread. |
594 | | class JSContextWrapper |
595 | | { |
596 | | public: |
597 | | static JSContextWrapper *Create(uint32_t aExtraHeapSize) |
598 | 0 | { |
599 | 0 | JSContext* cx = JS_NewContext(sContextHeapSize + aExtraHeapSize); |
600 | 0 | if (NS_WARN_IF(!cx)) |
601 | 0 | return nullptr; |
602 | 0 | |
603 | 0 | JSContextWrapper *entry = new JSContextWrapper(cx); |
604 | 0 | if (NS_FAILED(entry->Init())) { |
605 | 0 | delete entry; |
606 | 0 | return nullptr; |
607 | 0 | } |
608 | 0 | |
609 | 0 | return entry; |
610 | 0 | } |
611 | | |
612 | | JSContext *Context() const |
613 | 0 | { |
614 | 0 | return mContext; |
615 | 0 | } |
616 | | |
617 | | JSObject *Global() const |
618 | 0 | { |
619 | 0 | return mGlobal; |
620 | 0 | } |
621 | | |
622 | | ~JSContextWrapper() |
623 | 0 | { |
624 | 0 | mGlobal = nullptr; |
625 | 0 |
|
626 | 0 | MOZ_COUNT_DTOR(JSContextWrapper); |
627 | 0 |
|
628 | 0 | if (mContext) { |
629 | 0 | JS_DestroyContext(mContext); |
630 | 0 | } |
631 | 0 | } |
632 | | |
633 | | void SetOK() |
634 | 0 | { |
635 | 0 | mOK = true; |
636 | 0 | } |
637 | | |
638 | | bool IsOK() |
639 | 0 | { |
640 | 0 | return mOK; |
641 | 0 | } |
642 | | |
643 | | private: |
644 | | static const uint32_t sContextHeapSize = 4 << 20; // 4 MB |
645 | | |
646 | | JSContext *mContext; |
647 | | JS::PersistentRooted<JSObject*> mGlobal; |
648 | | bool mOK; |
649 | | |
650 | | static const JSClass sGlobalClass; |
651 | | |
652 | | explicit JSContextWrapper(JSContext* cx) |
653 | | : mContext(cx), mGlobal(cx, nullptr), mOK(false) |
654 | 0 | { |
655 | 0 | MOZ_COUNT_CTOR(JSContextWrapper); |
656 | 0 | } |
657 | | |
658 | | nsresult Init() |
659 | 0 | { |
660 | 0 | /* |
661 | 0 | * Not setting this will cause JS_CHECK_RECURSION to report false |
662 | 0 | * positives |
663 | 0 | */ |
664 | 0 | JS_SetNativeStackQuota(mContext, 128 * sizeof(size_t) * 1024); |
665 | 0 |
|
666 | 0 | JS::SetWarningReporter(mContext, PACWarningReporter); |
667 | 0 |
|
668 | 0 | if (!JS::InitSelfHostedCode(mContext)) { |
669 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
670 | 0 | } |
671 | 0 | |
672 | 0 | JS::RealmOptions options; |
673 | 0 | options.creationOptions().setNewCompartmentInSystemZone(); |
674 | 0 | mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, |
675 | 0 | JS::DontFireOnNewGlobalHook, options); |
676 | 0 | if (!mGlobal) { |
677 | 0 | JS_ClearPendingException(mContext); |
678 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
679 | 0 | } |
680 | 0 | JS::Rooted<JSObject*> global(mContext, mGlobal); |
681 | 0 |
|
682 | 0 | JSAutoRealm ar(mContext, global); |
683 | 0 | AutoPACErrorReporter aper(mContext); |
684 | 0 | if (!JS::InitRealmStandardClasses(mContext)) { |
685 | 0 | return NS_ERROR_FAILURE; |
686 | 0 | } |
687 | 0 | if (!JS_DefineFunctions(mContext, global, PACGlobalFunctions)) { |
688 | 0 | return NS_ERROR_FAILURE; |
689 | 0 | } |
690 | 0 | |
691 | 0 | JS_FireOnNewGlobalObject(mContext, global); |
692 | 0 |
|
693 | 0 | return NS_OK; |
694 | 0 | } |
695 | | }; |
696 | | |
697 | | static const JSClassOps sJSContextWrapperGlobalClassOps = { |
698 | | nullptr, nullptr, nullptr, nullptr, |
699 | | nullptr, nullptr, nullptr, nullptr, |
700 | | nullptr, nullptr, |
701 | | JS_GlobalObjectTraceHook |
702 | | }; |
703 | | |
704 | | const JSClass JSContextWrapper::sGlobalClass = { |
705 | | "PACResolutionThreadGlobal", |
706 | | JSCLASS_GLOBAL_FLAGS, |
707 | | &sJSContextWrapperGlobalClassOps |
708 | | }; |
709 | | |
710 | | void |
711 | | ProxyAutoConfig::SetThreadLocalIndex(uint32_t index) |
712 | 0 | { |
713 | 0 | sRunningIndex = index; |
714 | 0 | } |
715 | | |
716 | | nsresult |
717 | | ProxyAutoConfig::Init(const nsCString &aPACURI, |
718 | | const nsCString &aPACScript, |
719 | | bool aIncludePath, |
720 | | uint32_t aExtraHeapSize, |
721 | | nsIEventTarget *aEventTarget) |
722 | 0 | { |
723 | 0 | mShutdown = false; // Shutdown needs to be called prior to destruction |
724 | 0 |
|
725 | 0 | mPACURI = aPACURI; |
726 | 0 | mPACScript = sPacUtils; |
727 | 0 | mPACScript.Append(aPACScript); |
728 | 0 | mIncludePath = aIncludePath; |
729 | 0 | mExtraHeapSize = aExtraHeapSize; |
730 | 0 | mMainThreadEventTarget = aEventTarget; |
731 | 0 |
|
732 | 0 | if (!GetRunning()) |
733 | 0 | return SetupJS(); |
734 | 0 | |
735 | 0 | mJSNeedsSetup = true; |
736 | 0 | return NS_OK; |
737 | 0 | } |
738 | | |
739 | | nsresult |
740 | | ProxyAutoConfig::SetupJS() |
741 | 0 | { |
742 | 0 | mJSNeedsSetup = false; |
743 | 0 | MOZ_ASSERT(!GetRunning(), "JIT is running"); |
744 | 0 |
|
745 | 0 | delete mJSContext; |
746 | 0 | mJSContext = nullptr; |
747 | 0 |
|
748 | 0 | if (mPACScript.IsEmpty()) |
749 | 0 | return NS_ERROR_FAILURE; |
750 | 0 | |
751 | 0 | NS_GetCurrentThread()->SetCanInvokeJS(true); |
752 | 0 |
|
753 | 0 | mJSContext = JSContextWrapper::Create(mExtraHeapSize); |
754 | 0 | if (!mJSContext) |
755 | 0 | return NS_ERROR_FAILURE; |
756 | 0 | |
757 | 0 | JSContext* cx = mJSContext->Context(); |
758 | 0 | JSAutoRealm ar(cx, mJSContext->Global()); |
759 | 0 | AutoPACErrorReporter aper(cx); |
760 | 0 |
|
761 | 0 | // check if this is a data: uri so that we don't spam the js console with |
762 | 0 | // huge meaningless strings. this is not on the main thread, so it can't |
763 | 0 | // use nsIURI scheme methods |
764 | 0 | bool isDataURI = nsDependentCSubstring(mPACURI, 0, 5).LowerCaseEqualsASCII("data:", 5); |
765 | 0 |
|
766 | 0 | SetRunning(this); |
767 | 0 |
|
768 | 0 | JS::Rooted<JSObject*> global(cx, mJSContext->Global()); |
769 | 0 |
|
770 | 0 | JS::CompileOptions options(cx); |
771 | 0 | options.setFileAndLine(mPACURI.get(), 1); |
772 | 0 |
|
773 | 0 | JS::Rooted<JSScript*> script(cx); |
774 | 0 | if (!JS::CompileLatin1(cx, options, mPACScript.get(), mPACScript.Length(), |
775 | 0 | &script) || |
776 | 0 | !JS_ExecuteScript(cx, script)) |
777 | 0 | { |
778 | 0 | nsString alertMessage(NS_LITERAL_STRING("PAC file failed to install from ")); |
779 | 0 | if (isDataURI) { |
780 | 0 | alertMessage += NS_LITERAL_STRING("data: URI"); |
781 | 0 | } |
782 | 0 | else { |
783 | 0 | alertMessage += NS_ConvertUTF8toUTF16(mPACURI); |
784 | 0 | } |
785 | 0 | PACLogToConsole(alertMessage); |
786 | 0 | SetRunning(nullptr); |
787 | 0 | return NS_ERROR_FAILURE; |
788 | 0 | } |
789 | 0 | SetRunning(nullptr); |
790 | 0 |
|
791 | 0 | mJSContext->SetOK(); |
792 | 0 | nsString alertMessage(NS_LITERAL_STRING("PAC file installed from ")); |
793 | 0 | if (isDataURI) { |
794 | 0 | alertMessage += NS_LITERAL_STRING("data: URI"); |
795 | 0 | } |
796 | 0 | else { |
797 | 0 | alertMessage += NS_ConvertUTF8toUTF16(mPACURI); |
798 | 0 | } |
799 | 0 | PACLogToConsole(alertMessage); |
800 | 0 |
|
801 | 0 | // we don't need these now |
802 | 0 | mPACScript.Truncate(); |
803 | 0 | mPACURI.Truncate(); |
804 | 0 |
|
805 | 0 | return NS_OK; |
806 | 0 | } |
807 | | |
808 | | nsresult |
809 | | ProxyAutoConfig::GetProxyForURI(const nsCString &aTestURI, |
810 | | const nsCString &aTestHost, |
811 | | nsACString &result) |
812 | 0 | { |
813 | 0 | if (mJSNeedsSetup) |
814 | 0 | SetupJS(); |
815 | 0 |
|
816 | 0 | if (!mJSContext || !mJSContext->IsOK()) |
817 | 0 | return NS_ERROR_NOT_AVAILABLE; |
818 | 0 | |
819 | 0 | JSContext *cx = mJSContext->Context(); |
820 | 0 | JSAutoRealm ar(cx, mJSContext->Global()); |
821 | 0 | AutoPACErrorReporter aper(cx); |
822 | 0 |
|
823 | 0 | // the sRunning flag keeps a new PAC file from being installed |
824 | 0 | // while the event loop is spinning on a DNS function. Don't early return. |
825 | 0 | SetRunning(this); |
826 | 0 | mRunningHost = aTestHost; |
827 | 0 |
|
828 | 0 | nsresult rv = NS_ERROR_FAILURE; |
829 | 0 | nsCString clensedURI = aTestURI; |
830 | 0 |
|
831 | 0 | if (!mIncludePath) { |
832 | 0 | nsCOMPtr<nsIURLParser> urlParser = |
833 | 0 | do_GetService(NS_STDURLPARSER_CONTRACTID); |
834 | 0 | int32_t pathLen = 0; |
835 | 0 | if (urlParser) { |
836 | 0 | uint32_t schemePos; |
837 | 0 | int32_t schemeLen; |
838 | 0 | uint32_t authorityPos; |
839 | 0 | int32_t authorityLen; |
840 | 0 | uint32_t pathPos; |
841 | 0 | rv = urlParser->ParseURL(aTestURI.get(), aTestURI.Length(), |
842 | 0 | &schemePos, &schemeLen, |
843 | 0 | &authorityPos, &authorityLen, |
844 | 0 | &pathPos, &pathLen); |
845 | 0 | } |
846 | 0 | if (NS_SUCCEEDED(rv)) { |
847 | 0 | if (pathLen) { |
848 | 0 | // cut off the path but leave the initial slash |
849 | 0 | pathLen--; |
850 | 0 | } |
851 | 0 | aTestURI.Left(clensedURI, aTestURI.Length() - pathLen); |
852 | 0 | } |
853 | 0 | } |
854 | 0 |
|
855 | 0 | JS::RootedString uriString(cx, JS_NewStringCopyZ(cx, clensedURI.get())); |
856 | 0 | JS::RootedString hostString(cx, JS_NewStringCopyZ(cx, aTestHost.get())); |
857 | 0 |
|
858 | 0 | if (uriString && hostString) { |
859 | 0 | JS::AutoValueArray<2> args(cx); |
860 | 0 | args[0].setString(uriString); |
861 | 0 | args[1].setString(hostString); |
862 | 0 |
|
863 | 0 | JS::Rooted<JS::Value> rval(cx); |
864 | 0 | JS::Rooted<JSObject*> global(cx, mJSContext->Global()); |
865 | 0 | bool ok = JS_CallFunctionName(cx, global, "FindProxyForURL", args, &rval); |
866 | 0 |
|
867 | 0 | if (ok && rval.isString()) { |
868 | 0 | nsAutoJSString pacString; |
869 | 0 | if (pacString.init(cx, rval.toString())) { |
870 | 0 | CopyUTF16toUTF8(pacString, result); |
871 | 0 | rv = NS_OK; |
872 | 0 | } |
873 | 0 | } |
874 | 0 | } |
875 | 0 |
|
876 | 0 | mRunningHost.Truncate(); |
877 | 0 | SetRunning(nullptr); |
878 | 0 | return rv; |
879 | 0 | } |
880 | | |
881 | | void |
882 | | ProxyAutoConfig::GC() |
883 | 0 | { |
884 | 0 | if (!mJSContext || !mJSContext->IsOK()) |
885 | 0 | return; |
886 | 0 | |
887 | 0 | JSAutoRealm ar(mJSContext->Context(), mJSContext->Global()); |
888 | 0 | JS_MaybeGC(mJSContext->Context()); |
889 | 0 | } |
890 | | |
891 | | ProxyAutoConfig::~ProxyAutoConfig() |
892 | 0 | { |
893 | 0 | MOZ_COUNT_DTOR(ProxyAutoConfig); |
894 | 0 | MOZ_ASSERT(mShutdown, "Shutdown must be called before dtor."); |
895 | 0 | NS_ASSERTION(!mJSContext, |
896 | 0 | "~ProxyAutoConfig leaking JS context that " |
897 | 0 | "should have been deleted on pac thread"); |
898 | 0 | } |
899 | | |
900 | | void |
901 | | ProxyAutoConfig::Shutdown() |
902 | 0 | { |
903 | 0 | MOZ_ASSERT(!NS_IsMainThread(), "wrong thread for shutdown"); |
904 | 0 |
|
905 | 0 | if (NS_WARN_IF(GetRunning()) || mShutdown) { |
906 | 0 | return; |
907 | 0 | } |
908 | 0 | |
909 | 0 | mShutdown = true; |
910 | 0 | delete mJSContext; |
911 | 0 | mJSContext = nullptr; |
912 | 0 | } |
913 | | |
914 | | bool |
915 | | ProxyAutoConfig::SrcAddress(const NetAddr *remoteAddress, nsCString &localAddress) |
916 | 0 | { |
917 | 0 | PRFileDesc *fd; |
918 | 0 | fd = PR_OpenUDPSocket(remoteAddress->raw.family); |
919 | 0 | if (!fd) |
920 | 0 | return false; |
921 | 0 | |
922 | 0 | PRNetAddr prRemoteAddress; |
923 | 0 | NetAddrToPRNetAddr(remoteAddress, &prRemoteAddress); |
924 | 0 | if (PR_Connect(fd, &prRemoteAddress, 0) != PR_SUCCESS) { |
925 | 0 | PR_Close(fd); |
926 | 0 | return false; |
927 | 0 | } |
928 | 0 | |
929 | 0 | PRNetAddr localName; |
930 | 0 | if (PR_GetSockName(fd, &localName) != PR_SUCCESS) { |
931 | 0 | PR_Close(fd); |
932 | 0 | return false; |
933 | 0 | } |
934 | 0 | |
935 | 0 | PR_Close(fd); |
936 | 0 |
|
937 | 0 | char dottedDecimal[128]; |
938 | 0 | if (PR_NetAddrToString(&localName, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS) |
939 | 0 | return false; |
940 | 0 | |
941 | 0 | localAddress.Assign(dottedDecimal); |
942 | 0 |
|
943 | 0 | return true; |
944 | 0 | } |
945 | | |
946 | | // hostName is run through a dns lookup and then a udp socket is connected |
947 | | // to the result. If that all works, the local IP address of the socket is |
948 | | // returned to the javascript caller and |*aResult| is set to true. Otherwise |
949 | | // |*aResult| is set to false. |
950 | | bool |
951 | | ProxyAutoConfig::MyIPAddressTryHost(const nsCString &hostName, |
952 | | unsigned int timeout, |
953 | | const JS::CallArgs &aArgs, |
954 | | bool* aResult) |
955 | 0 | { |
956 | 0 | *aResult = false; |
957 | 0 |
|
958 | 0 | NetAddr remoteAddress; |
959 | 0 | nsAutoCString localDottedDecimal; |
960 | 0 | JSContext *cx = mJSContext->Context(); |
961 | 0 |
|
962 | 0 | if (PACResolve(hostName, &remoteAddress, timeout) && |
963 | 0 | SrcAddress(&remoteAddress, localDottedDecimal)) { |
964 | 0 | JSString *dottedDecimalString = |
965 | 0 | JS_NewStringCopyZ(cx, localDottedDecimal.get()); |
966 | 0 | if (!dottedDecimalString) { |
967 | 0 | return false; |
968 | 0 | } |
969 | 0 | |
970 | 0 | *aResult = true; |
971 | 0 | aArgs.rval().setString(dottedDecimalString); |
972 | 0 | } |
973 | 0 | return true; |
974 | 0 | } |
975 | | |
976 | | bool |
977 | | ProxyAutoConfig::MyIPAddress(const JS::CallArgs &aArgs) |
978 | 0 | { |
979 | 0 | nsAutoCString remoteDottedDecimal; |
980 | 0 | nsAutoCString localDottedDecimal; |
981 | 0 | JSContext *cx = mJSContext->Context(); |
982 | 0 | JS::RootedValue v(cx); |
983 | 0 | JS::Rooted<JSObject*> global(cx, mJSContext->Global()); |
984 | 0 |
|
985 | 0 | bool useMultihomedDNS = |
986 | 0 | JS_GetProperty(cx, global, "pacUseMultihomedDNS", &v) && |
987 | 0 | !v.isUndefined() && ToBoolean(v); |
988 | 0 |
|
989 | 0 | // first, lookup the local address of a socket connected |
990 | 0 | // to the host of uri being resolved by the pac file. This is |
991 | 0 | // v6 safe.. but is the last step like that |
992 | 0 | bool rvalAssigned = false; |
993 | 0 | if (useMultihomedDNS) { |
994 | 0 | if (!MyIPAddressTryHost(mRunningHost, kTimeout, aArgs, &rvalAssigned) || |
995 | 0 | rvalAssigned) { |
996 | 0 | return rvalAssigned; |
997 | 0 | } |
998 | 0 | } else { |
999 | 0 | // we can still do the fancy multi homing thing if the host is a literal |
1000 | 0 | PRNetAddr tempAddr; |
1001 | 0 | memset(&tempAddr, 0, sizeof(PRNetAddr)); |
1002 | 0 | if ((PR_StringToNetAddr(mRunningHost.get(), &tempAddr) == PR_SUCCESS) && |
1003 | 0 | (!MyIPAddressTryHost(mRunningHost, kTimeout, aArgs, &rvalAssigned) || |
1004 | 0 | rvalAssigned)) { |
1005 | 0 | return rvalAssigned; |
1006 | 0 | } |
1007 | 0 | } |
1008 | 0 | |
1009 | 0 | // next, look for a route to a public internet address that doesn't need DNS. |
1010 | 0 | // This is the google anycast dns address, but it doesn't matter if it |
1011 | 0 | // remains operable (as we don't contact it) as long as the address stays |
1012 | 0 | // in commonly routed IP address space. |
1013 | 0 | remoteDottedDecimal.AssignLiteral("8.8.8.8"); |
1014 | 0 | if (!MyIPAddressTryHost(remoteDottedDecimal, 0, aArgs, &rvalAssigned) || |
1015 | 0 | rvalAssigned) { |
1016 | 0 | return rvalAssigned; |
1017 | 0 | } |
1018 | 0 | |
1019 | 0 | // finally, use the old algorithm based on the local hostname |
1020 | 0 | nsAutoCString hostName; |
1021 | 0 | nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID); |
1022 | 0 | // without multihomedDNS use such a short timeout that we are basically |
1023 | 0 | // just looking at the cache for raw dotted decimals |
1024 | 0 | uint32_t timeout = useMultihomedDNS ? kTimeout : 1; |
1025 | 0 | if (dns && NS_SUCCEEDED(dns->GetMyHostName(hostName)) && |
1026 | 0 | PACResolveToString(hostName, localDottedDecimal, timeout)) { |
1027 | 0 | JSString *dottedDecimalString = |
1028 | 0 | JS_NewStringCopyZ(cx, localDottedDecimal.get()); |
1029 | 0 | if (!dottedDecimalString) { |
1030 | 0 | return false; |
1031 | 0 | } |
1032 | 0 | |
1033 | 0 | aArgs.rval().setString(dottedDecimalString); |
1034 | 0 | return true; |
1035 | 0 | } |
1036 | 0 | |
1037 | 0 | // next try a couple RFC 1918 variants.. maybe there is a |
1038 | 0 | // local route |
1039 | 0 | remoteDottedDecimal.AssignLiteral("192.168.0.1"); |
1040 | 0 | if (!MyIPAddressTryHost(remoteDottedDecimal, 0, aArgs, &rvalAssigned) || |
1041 | 0 | rvalAssigned) { |
1042 | 0 | return rvalAssigned; |
1043 | 0 | } |
1044 | 0 | |
1045 | 0 | // more RFC 1918 |
1046 | 0 | remoteDottedDecimal.AssignLiteral("10.0.0.1"); |
1047 | 0 | if (!MyIPAddressTryHost(remoteDottedDecimal, 0, aArgs, &rvalAssigned) || |
1048 | 0 | rvalAssigned) { |
1049 | 0 | return rvalAssigned; |
1050 | 0 | } |
1051 | 0 | |
1052 | 0 | // who knows? let's fallback to localhost |
1053 | 0 | localDottedDecimal.AssignLiteral("127.0.0.1"); |
1054 | 0 | JSString *dottedDecimalString = |
1055 | 0 | JS_NewStringCopyZ(cx, localDottedDecimal.get()); |
1056 | 0 | if (!dottedDecimalString) { |
1057 | 0 | return false; |
1058 | 0 | } |
1059 | 0 | |
1060 | 0 | aArgs.rval().setString(dottedDecimalString); |
1061 | 0 | return true; |
1062 | 0 | } |
1063 | | |
1064 | | } // namespace net |
1065 | | } // namespace mozilla |