@@ -76,6 +76,7 @@ inline const char* ToErrorCodeString(int status) {
76
76
V (ETIMEOUT)
77
77
#undef V
78
78
}
79
+
79
80
return " UNKNOWN_ARES_ERROR" ;
80
81
}
81
82
@@ -280,6 +281,96 @@ static Local<Array> HostentToNames(Environment* env, struct hostent* host) {
280
281
return scope.Escape (names);
281
282
}
282
283
284
+ void safe_free_hostent (struct hostent * host) {
285
+ int idx;
286
+
287
+ if (host->h_addr_list != nullptr ) {
288
+ idx = 0 ;
289
+ while (host->h_addr_list [idx]) {
290
+ free (host->h_addr_list [idx++]);
291
+ }
292
+ free (host->h_addr_list );
293
+ host->h_addr_list = 0 ;
294
+ }
295
+
296
+ if (host->h_aliases != nullptr ) {
297
+ idx = 0 ;
298
+ while (host->h_aliases [idx]) {
299
+ free (host->h_aliases [idx++]);
300
+ }
301
+ free (host->h_aliases );
302
+ host->h_aliases = 0 ;
303
+ }
304
+
305
+ if (host->h_name != nullptr ) {
306
+ free (host->h_name );
307
+ }
308
+
309
+ host->h_addrtype = host->h_length = 0 ;
310
+ }
311
+
312
+ void cares_wrap_hostent_cpy (struct hostent * dest, struct hostent * src) {
313
+ dest->h_addr_list = nullptr ;
314
+ dest->h_addrtype = 0 ;
315
+ dest->h_aliases = nullptr ;
316
+ dest->h_length = 0 ;
317
+ dest->h_name = nullptr ;
318
+
319
+ /* copy `h_name` */
320
+ size_t name_size = strlen (src->h_name ) + 1 ;
321
+ dest->h_name = static_cast <char *>(node::Malloc (name_size));
322
+ memcpy (dest->h_name , src->h_name , name_size);
323
+
324
+ /* copy `h_aliases` */
325
+ size_t alias_count;
326
+ size_t cur_alias_length;
327
+ for (alias_count = 0 ;
328
+ src->h_aliases [alias_count] != nullptr ;
329
+ alias_count++) {
330
+ }
331
+
332
+ dest->h_aliases = static_cast <char **>(node::Malloc ((alias_count + 1 ) *
333
+ sizeof (char *)));
334
+ for (size_t i = 0 ; i < alias_count; i++) {
335
+ cur_alias_length = strlen (src->h_aliases [i]);
336
+ dest->h_aliases [i] = static_cast <char *>(node::Malloc (cur_alias_length + 1 ));
337
+ memcpy (dest->h_aliases [i], src->h_aliases [i], cur_alias_length + 1 );
338
+ }
339
+ dest->h_aliases [alias_count] = nullptr ;
340
+
341
+ /* copy `h_addr_list` */
342
+ size_t list_count;
343
+ for (list_count = 0 ;
344
+ src->h_addr_list [list_count] != nullptr ;
345
+ list_count++) {
346
+ }
347
+
348
+ dest->h_addr_list = static_cast <char **>(node::Malloc ((list_count + 1 ) *
349
+ sizeof (char *)));
350
+ for (size_t i = 0 ; i < list_count; i++) {
351
+ dest->h_addr_list [i] = static_cast <char *>(node::Malloc (src->h_length ));
352
+ memcpy (dest->h_addr_list [i], src->h_addr_list [i], src->h_length );
353
+ }
354
+ dest->h_addr_list [list_count] = nullptr ;
355
+
356
+ /* work after work */
357
+ dest->h_length = src->h_length ;
358
+ dest->h_addrtype = src->h_addrtype ;
359
+ }
360
+
361
+ class QueryWrap ;
362
+ struct CaresAsyncData {
363
+ QueryWrap* wrap;
364
+ int status;
365
+ bool is_host;
366
+ union {
367
+ hostent* host;
368
+ unsigned char * buf;
369
+ } data;
370
+ int len;
371
+
372
+ uv_async_t async_handle;
373
+ };
283
374
284
375
class QueryWrap : public AsyncWrap {
285
376
public:
@@ -311,30 +402,80 @@ class QueryWrap : public AsyncWrap {
311
402
return static_cast <void *>(this );
312
403
}
313
404
314
- static void Callback (void *arg, int status, int timeouts,
315
- unsigned char * answer_buf, int answer_len) {
316
- QueryWrap* wrap = static_cast <QueryWrap*>(arg);
405
+ static void CaresAsyncClose (uv_handle_t * handle) {
406
+ uv_async_t * async = reinterpret_cast <uv_async_t *>(handle);
407
+ auto data = static_cast <struct CaresAsyncData *>(async->data );
408
+ delete data->wrap ;
409
+ delete data;
410
+ }
411
+
412
+ static void CaresAsyncCb (uv_async_t * handle) {
413
+ auto data = static_cast <struct CaresAsyncData *>(handle->data );
414
+
415
+ QueryWrap* wrap = data->wrap ;
416
+ int status = data->status ;
317
417
318
418
if (status != ARES_SUCCESS) {
319
419
wrap->ParseError (status);
420
+ } else if (!data->is_host ) {
421
+ unsigned char * buf = data->data .buf ;
422
+ wrap->Parse (buf, data->len );
423
+ free (buf);
320
424
} else {
321
- wrap->Parse (answer_buf, answer_len);
425
+ hostent* host = data->data .host ;
426
+ wrap->Parse (host);
427
+ safe_free_hostent (host);
428
+ free (host);
322
429
}
323
430
324
- delete wrap ;
431
+ uv_close ( reinterpret_cast < uv_handle_t *>(handle), CaresAsyncClose) ;
325
432
}
326
433
327
434
static void Callback (void *arg, int status, int timeouts,
328
- struct hostent * host ) {
435
+ unsigned char * answer_buf, int answer_len ) {
329
436
QueryWrap* wrap = static_cast <QueryWrap*>(arg);
330
437
331
- if (status != ARES_SUCCESS) {
332
- wrap-> ParseError (status);
333
- } else {
334
- wrap-> Parse (host );
438
+ unsigned char * buf_copy = nullptr ;
439
+ if (status == ARES_SUCCESS) {
440
+ buf_copy = static_cast < unsigned char *>( node::Malloc (answer_len));
441
+ memcpy (buf_copy, answer_buf, answer_len );
335
442
}
336
443
337
- delete wrap;
444
+ CaresAsyncData* data = new CaresAsyncData ();
445
+ data->status = status;
446
+ data->wrap = wrap;
447
+ data->is_host = false ;
448
+ data->data .buf = buf_copy;
449
+ data->len = answer_len;
450
+
451
+ uv_async_t * async_handle = &data->async_handle ;
452
+ uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
453
+
454
+ async_handle->data = data;
455
+ uv_async_send (async_handle);
456
+ }
457
+
458
+ static void Callback (void *arg, int status, int timeouts,
459
+ struct hostent * host) {
460
+ QueryWrap* wrap = static_cast <QueryWrap*>(arg);
461
+
462
+ struct hostent * host_copy = nullptr ;
463
+ if (status == ARES_SUCCESS) {
464
+ host_copy = static_cast <hostent*>(node::Malloc (sizeof (hostent)));
465
+ cares_wrap_hostent_cpy (host_copy, host);
466
+ }
467
+
468
+ CaresAsyncData* data = new CaresAsyncData ();
469
+ data->status = status;
470
+ data->data .host = host_copy;
471
+ data->wrap = wrap;
472
+ data->is_host = true ;
473
+
474
+ uv_async_t * async_handle = &data->async_handle ;
475
+ uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
476
+
477
+ async_handle->data = data;
478
+ uv_async_send (async_handle);
338
479
}
339
480
340
481
void CallOnComplete (Local<Value> answer,
0 commit comments