1'use strict';
2
3const {
4  ObjectDefineProperty,
5  ReflectApply,
6  ArrayPrototypeMap,
7  Symbol,
8} = primordials;
9
10const {
11  codes: {
12    ERR_INVALID_ARG_TYPE,
13    ERR_INVALID_ARG_VALUE,
14  },
15  dnsException,
16} = require('internal/errors');
17
18const {
19  createResolverClass,
20} = require('internal/dns/utils');
21
22const {
23  validateFunction,
24  validateString,
25} = require('internal/validators');
26
27const {
28  QueryReqWrap,
29} = internalBinding('cares_wrap');
30
31const {
32  hasObserver,
33  startPerf,
34  stopPerf,
35} = require('internal/perf/observe');
36
37const kPerfHooksDnsLookupResolveContext = Symbol('kPerfHooksDnsLookupResolveContext');
38
39function onresolve(err, result, ttls) {
40  if (ttls && this.ttl)
41    result = ArrayPrototypeMap(
42      result, (address, index) => ({ address, ttl: ttls[index] }));
43
44  if (err)
45    this.callback(dnsException(err, this.bindingName, this.hostname));
46  else {
47    this.callback(null, result);
48    if (this[kPerfHooksDnsLookupResolveContext] && hasObserver('dns')) {
49      stopPerf(this, kPerfHooksDnsLookupResolveContext, { detail: { result } });
50    }
51  }
52}
53
54function resolver(bindingName) {
55  function query(name, /* options, */ callback) {
56    let options;
57    if (arguments.length > 2) {
58      options = callback;
59      callback = arguments[2];
60    }
61
62    validateString(name, 'name');
63    validateFunction(callback, 'callback');
64
65    const req = new QueryReqWrap();
66    req.bindingName = bindingName;
67    req.callback = callback;
68    req.hostname = name;
69    req.oncomplete = onresolve;
70    req.ttl = !!(options && options.ttl);
71    const err = this._handle[bindingName](req, name);
72    if (err) throw dnsException(err, bindingName, name);
73    if (hasObserver('dns')) {
74      startPerf(req, kPerfHooksDnsLookupResolveContext, {
75        type: 'dns',
76        name: bindingName,
77        detail: {
78          host: name,
79          ttl: req.ttl,
80        },
81      });
82    }
83    return req;
84  }
85  ObjectDefineProperty(query, 'name', { __proto__: null, value: bindingName });
86  return query;
87}
88
89// This is the callback-based resolver. There is another similar
90// resolver in dns/promises.js with resolve methods that are based
91// on promises instead.
92const { Resolver, resolveMap } = createResolverClass(resolver);
93Resolver.prototype.resolve = resolve;
94
95function resolve(hostname, rrtype, callback) {
96  let resolver;
97  if (typeof rrtype === 'string') {
98    resolver = resolveMap[rrtype];
99  } else if (typeof rrtype === 'function') {
100    resolver = resolveMap.A;
101    callback = rrtype;
102  } else {
103    throw new ERR_INVALID_ARG_TYPE('rrtype', 'string', rrtype);
104  }
105
106  if (typeof resolver === 'function') {
107    return ReflectApply(resolver, this, [hostname, callback]);
108  }
109  throw new ERR_INVALID_ARG_VALUE('rrtype', rrtype);
110}
111
112module.exports = {
113  Resolver,
114};
115