diff --git a/lib/dns.js b/lib/dns.js index ad919cc477..10214790de 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -170,6 +170,7 @@ exports.resolveMx = resolveMap.MX = resolver('queryMx'); exports.resolveNs = resolveMap.NS = resolver('queryNs'); exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); +exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 22c7ec4975..b7ba82870f 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -609,6 +609,66 @@ class QuerySrvWrap: public QueryWrap { } }; +class QueryNaptrWrap: public QueryWrap { + public: + int Send(const char* name) { + ares_query(ares_channel, + name, + ns_c_in, + ns_t_naptr, + Callback, + GetQueryArg()); + return 0; + } + + protected: + void Parse(unsigned char* buf, int len) { + HandleScope scope; + + ares_naptr_reply* naptr_start; + int status = ares_parse_naptr_reply(buf, len, &naptr_start); + + if (status != ARES_SUCCESS) { + this->ParseError(status); + return; + } + + Local naptr_records = Array::New(); + Local flags_symbol = String::NewSymbol("flags"); + Local service_symbol = String::NewSymbol("service"); + Local regexp_symbol = String::NewSymbol("regexp"); + Local replacement_symbol = String::NewSymbol("replacement"); + Local order_symbol = String::NewSymbol("order"); + Local preference_symbol = String::NewSymbol("preference"); + + int i = 0; + for (ares_naptr_reply* naptr_current = naptr_start; + naptr_current; + naptr_current = naptr_current->next) { + + Local naptr_record = Object::New(); + + naptr_record->Set(flags_symbol, + String::New(reinterpret_cast(naptr_current->flags))); + naptr_record->Set(service_symbol, + String::New(reinterpret_cast(naptr_current->service))); + naptr_record->Set(regexp_symbol, + String::New(reinterpret_cast(naptr_current->regexp))); + naptr_record->Set(replacement_symbol, + String::New(naptr_current->replacement)); + naptr_record->Set(order_symbol, Integer::New(naptr_current->order)); + naptr_record->Set(preference_symbol, + Integer::New(naptr_current->preference)); + + naptr_records->Set(Integer::New(i++), naptr_record); + } + + ares_free_data(naptr_start); + + this->CallOnComplete(naptr_records); + } +}; + class GetHostByAddrWrap: public QueryWrap { public: @@ -908,6 +968,7 @@ static void Initialize(Handle target) { NODE_SET_METHOD(target, "queryNs", Query); NODE_SET_METHOD(target, "queryTxt", Query); NODE_SET_METHOD(target, "querySrv", Query); + NODE_SET_METHOD(target, "queryNaptr", Query); NODE_SET_METHOD(target, "getHostByAddr", Query); NODE_SET_METHOD(target, "getHostByName", QueryWithFamily); diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index b781565c30..7777223996 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -219,6 +219,30 @@ TEST(function test_resolveSrv(done) { checkWrap(req); }); +TEST(function test_resolveNaptr(done) { + var req = dns.resolveNaptr('sip2sip.info', function(err, result) { + if (err) throw err; + + assert.ok(result.length > 0); + + for (var i = 0; i < result.length; i++) { + var item = result[i]; + assert.ok(item); + assert.ok(typeof item === 'object'); + + assert.ok(typeof item.flags === 'string'); + assert.ok(typeof item.service === 'string'); + assert.ok(typeof item.regexp === 'string'); + assert.ok(typeof item.replacement === 'string'); + assert.ok(typeof item.order === 'number'); + assert.ok(typeof item.preference === 'number'); + } + + done(); + }); + + checkWrap(req); +}); TEST(function test_resolveCname(done) { var req = dns.resolveCname('www.microsoft.com', function(err, names) {