@@ -91,6 +91,40 @@ var channel = new dns.Channel({SOCK_STATE_CB: function(socket, read, write) {
9191 updateTimer ( ) ;
9292} } ) ;
9393
94+ // c-ares invokes a callback either synchronously or asynchronously,
95+ // but the dns API should always invoke a callback asynchronously.
96+ //
97+ // This function makes sure that the callback is invoked asynchronously.
98+ // It returns a function that invokes the callback within nextTick().
99+ //
100+ // To avoid invoking unnecessary nextTick(), `immediately` property of
101+ // returned function should be set to true after c-ares returned.
102+ //
103+ // Usage:
104+ //
105+ // function someAPI(callback) {
106+ // callback = makeAsync(callback);
107+ // channel.someAPI(..., callback);
108+ // callback.immediately = true;
109+ // }
110+ function makeAsync ( callback ) {
111+ if ( typeof callback !== 'function' ) {
112+ return callback ;
113+ }
114+ return function asyncCallback ( ) {
115+ if ( asyncCallback . immediately ) {
116+ // The API already returned, we can invoke the callback immediately.
117+ callback . apply ( null , arguments ) ;
118+ } else {
119+ var args = arguments ;
120+ process . nextTick ( function ( ) {
121+ callback . apply ( null , args ) ;
122+ } ) ;
123+ }
124+ } ;
125+ }
126+
127+
94128exports . resolve = function ( domain , type_ , callback_ ) {
95129 var type , callback ;
96130 if ( typeof ( type_ ) == 'string' ) {
@@ -121,13 +155,17 @@ function familyToSym(family) {
121155
122156exports . getHostByName = function ( domain , family /*=4*/ , callback ) {
123157 if ( typeof family === 'function' ) { callback = family ; family = null ; }
158+ callback = makeAsync ( callback ) ;
124159 channel . getHostByName ( domain , familyToSym ( family ) , callback ) ;
160+ callback . immediately = true ;
125161} ;
126162
127163
128164exports . getHostByAddr = function ( address , family /*=4*/ , callback ) {
129165 if ( typeof family === 'function' ) { callback = family ; family = null ; }
166+ callback = makeAsync ( callback ) ;
130167 channel . getHostByAddr ( address , familyToSym ( family ) , callback ) ;
168+ callback . immediately = true ;
131169} ;
132170
133171
@@ -148,6 +186,7 @@ exports.lookup = function(domain, family, callback) {
148186 throw new Error ( 'invalid argument: "family" must be 4 or 6' ) ;
149187 }
150188 }
189+ callback = makeAsync ( callback ) ;
151190
152191 if ( ! domain ) {
153192 callback ( null , null , family === 6 ? 6 : 4 ) ;
@@ -166,6 +205,7 @@ exports.lookup = function(domain, family, callback) {
166205 process . binding ( 'net' ) . getaddrinfo ( domain , 4 , function ( err , domains4 ) {
167206 callback ( err , domains4 [ 0 ] , 4 ) ;
168207 } ) ;
208+ callback . immediately = true ;
169209 return ;
170210 }
171211
@@ -183,6 +223,7 @@ exports.lookup = function(domain, family, callback) {
183223 callback ( err , [ ] ) ;
184224 }
185225 } ) ;
226+ callback . immediately = true ;
186227 return ;
187228 }
188229
@@ -200,46 +241,63 @@ exports.lookup = function(domain, family, callback) {
200241 } ) ;
201242 }
202243 } ) ;
244+ callback . immediately = true ;
203245} ;
204246
205247
206248exports . resolve4 = function ( domain , callback ) {
249+ callback = makeAsync ( callback ) ;
207250 channel . query ( domain , dns . A , callback ) ;
251+ callback . immediately = true ;
208252} ;
209253
210254
211255exports . resolve6 = function ( domain , callback ) {
256+ callback = makeAsync ( callback ) ;
212257 channel . query ( domain , dns . AAAA , callback ) ;
258+ callback . immediately = true ;
213259} ;
214260
215261
216262exports . resolveMx = function ( domain , callback ) {
263+ callback = makeAsync ( callback ) ;
217264 channel . query ( domain , dns . MX , callback ) ;
265+ callback . immediately = true ;
218266} ;
219267
220268
221269exports . resolveTxt = function ( domain , callback ) {
270+ callback = makeAsync ( callback ) ;
222271 channel . query ( domain , dns . TXT , callback ) ;
272+ callback . immediately = true ;
223273} ;
224274
225275
226276exports . resolveSrv = function ( domain , callback ) {
277+ callback = makeAsync ( callback ) ;
227278 channel . query ( domain , dns . SRV , callback ) ;
279+ callback . immediately = true ;
228280} ;
229281
230282
231283exports . reverse = function ( domain , callback ) {
284+ callback = makeAsync ( callback ) ;
232285 channel . query ( domain , dns . PTR , callback ) ;
286+ callback . immediately = true ;
233287} ;
234288
235289
236290exports . resolveNs = function ( domain , callback ) {
291+ callback = makeAsync ( callback ) ;
237292 channel . query ( domain , dns . NS , callback ) ;
293+ callback . immediately = true ;
238294} ;
239295
240296
241297exports . resolveCname = function ( domain , callback ) {
298+ callback = makeAsync ( callback ) ;
242299 channel . query ( domain , dns . CNAME , callback ) ;
300+ callback . immediately = true ;
243301} ;
244302
245303var resolveMap = { A : exports . resolve4 ,
0 commit comments