@@ -98,6 +98,7 @@ inline const char* ToErrorCodeString(int status) {
98
98
V (ETIMEOUT)
99
99
#undef V
100
100
}
101
+
101
102
return " UNKNOWN_ARES_ERROR" ;
102
103
}
103
104
@@ -296,6 +297,94 @@ Local<Array> HostentToNames(Environment* env, struct hostent* host) {
296
297
return scope.Escape (names);
297
298
}
298
299
300
+ void safe_free_hostent (struct hostent * host) {
301
+ int idx;
302
+
303
+ if (host->h_addr_list != nullptr ) {
304
+ idx = 0 ;
305
+ while (host->h_addr_list [idx]) {
306
+ free (host->h_addr_list [idx++]);
307
+ }
308
+ free (host->h_addr_list );
309
+ host->h_addr_list = 0 ;
310
+ }
311
+
312
+ if (host->h_aliases != nullptr ) {
313
+ idx = 0 ;
314
+ while (host->h_aliases [idx]) {
315
+ free (host->h_aliases [idx++]);
316
+ }
317
+ free (host->h_aliases );
318
+ host->h_aliases = 0 ;
319
+ }
320
+
321
+ if (host->h_name != nullptr ) {
322
+ free (host->h_name );
323
+ }
324
+
325
+ host->h_addrtype = host->h_length = 0 ;
326
+ }
327
+
328
+ void cares_wrap_hostent_cpy (struct hostent * dest, struct hostent * src) {
329
+ dest->h_addr_list = nullptr ;
330
+ dest->h_addrtype = 0 ;
331
+ dest->h_aliases = nullptr ;
332
+ dest->h_length = 0 ;
333
+ dest->h_name = nullptr ;
334
+
335
+ /* copy `h_name` */
336
+ size_t name_size = strlen (src->h_name ) + 1 ;
337
+ dest->h_name = node::Malloc<char >(name_size);
338
+ memcpy (dest->h_name , src->h_name , name_size);
339
+
340
+ /* copy `h_aliases` */
341
+ size_t alias_count;
342
+ size_t cur_alias_length;
343
+ for (alias_count = 0 ;
344
+ src->h_aliases [alias_count] != nullptr ;
345
+ alias_count++) {
346
+ }
347
+
348
+ dest->h_aliases = node::Malloc<char *>(alias_count + 1 );
349
+ for (size_t i = 0 ; i < alias_count; i++) {
350
+ cur_alias_length = strlen (src->h_aliases [i]);
351
+ dest->h_aliases [i] = node::Malloc (cur_alias_length + 1 );
352
+ memcpy (dest->h_aliases [i], src->h_aliases [i], cur_alias_length + 1 );
353
+ }
354
+ dest->h_aliases [alias_count] = nullptr ;
355
+
356
+ /* copy `h_addr_list` */
357
+ size_t list_count;
358
+ for (list_count = 0 ;
359
+ src->h_addr_list [list_count] != nullptr ;
360
+ list_count++) {
361
+ }
362
+
363
+ dest->h_addr_list = node::Malloc<char *>(list_count + 1 );
364
+ for (size_t i = 0 ; i < list_count; i++) {
365
+ dest->h_addr_list [i] = node::Malloc (src->h_length );
366
+ memcpy (dest->h_addr_list [i], src->h_addr_list [i], src->h_length );
367
+ }
368
+ dest->h_addr_list [list_count] = nullptr ;
369
+
370
+ /* work after work */
371
+ dest->h_length = src->h_length ;
372
+ dest->h_addrtype = src->h_addrtype ;
373
+ }
374
+
375
+ class QueryWrap ;
376
+ struct CaresAsyncData {
377
+ QueryWrap* wrap;
378
+ int status;
379
+ bool is_host;
380
+ union {
381
+ hostent* host;
382
+ unsigned char * buf;
383
+ } data;
384
+ int len;
385
+
386
+ uv_async_t async_handle;
387
+ };
299
388
300
389
class QueryWrap : public AsyncWrap {
301
390
public:
@@ -328,30 +417,80 @@ class QueryWrap : public AsyncWrap {
328
417
return static_cast <void *>(this );
329
418
}
330
419
331
- static void Callback (void *arg, int status, int timeouts,
332
- unsigned char * answer_buf, int answer_len) {
333
- QueryWrap* wrap = static_cast <QueryWrap*>(arg);
420
+ static void CaresAsyncClose (uv_handle_t * handle) {
421
+ uv_async_t * async = reinterpret_cast <uv_async_t *>(handle);
422
+ auto data = static_cast <struct CaresAsyncData *>(async->data );
423
+ delete data->wrap ;
424
+ delete data;
425
+ }
426
+
427
+ static void CaresAsyncCb (uv_async_t * handle) {
428
+ auto data = static_cast <struct CaresAsyncData *>(handle->data );
429
+
430
+ QueryWrap* wrap = data->wrap ;
431
+ int status = data->status ;
334
432
335
433
if (status != ARES_SUCCESS) {
336
434
wrap->ParseError (status);
435
+ } else if (!data->is_host ) {
436
+ unsigned char * buf = data->data .buf ;
437
+ wrap->Parse (buf, data->len );
438
+ free (buf);
337
439
} else {
338
- wrap->Parse (answer_buf, answer_len);
440
+ hostent* host = data->data .host ;
441
+ wrap->Parse (host);
442
+ safe_free_hostent (host);
443
+ free (host);
339
444
}
340
445
341
- delete wrap ;
446
+ uv_close ( reinterpret_cast < uv_handle_t *>(handle), CaresAsyncClose) ;
342
447
}
343
448
344
449
static void Callback (void *arg, int status, int timeouts,
345
- struct hostent * host ) {
450
+ unsigned char * answer_buf, int answer_len ) {
346
451
QueryWrap* wrap = static_cast <QueryWrap*>(arg);
347
452
348
- if (status != ARES_SUCCESS) {
349
- wrap-> ParseError (status);
350
- } else {
351
- wrap-> Parse (host );
453
+ unsigned char * buf_copy = nullptr ;
454
+ if (status == ARES_SUCCESS) {
455
+ buf_copy = node::Malloc< unsigned char >(answer_len);
456
+ memcpy (buf_copy, answer_buf, answer_len );
352
457
}
353
458
354
- delete wrap;
459
+ CaresAsyncData* data = new CaresAsyncData ();
460
+ data->status = status;
461
+ data->wrap = wrap;
462
+ data->is_host = false ;
463
+ data->data .buf = buf_copy;
464
+ data->len = answer_len;
465
+
466
+ uv_async_t * async_handle = &data->async_handle ;
467
+ uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
468
+
469
+ async_handle->data = data;
470
+ uv_async_send (async_handle);
471
+ }
472
+
473
+ static void Callback (void *arg, int status, int timeouts,
474
+ struct hostent * host) {
475
+ QueryWrap* wrap = static_cast <QueryWrap*>(arg);
476
+
477
+ struct hostent * host_copy = nullptr ;
478
+ if (status == ARES_SUCCESS) {
479
+ host_copy = node::Malloc<hostent>(1 );
480
+ cares_wrap_hostent_cpy (host_copy, host);
481
+ }
482
+
483
+ CaresAsyncData* data = new CaresAsyncData ();
484
+ data->status = status;
485
+ data->data .host = host_copy;
486
+ data->wrap = wrap;
487
+ data->is_host = true ;
488
+
489
+ uv_async_t * async_handle = &data->async_handle ;
490
+ uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
491
+
492
+ async_handle->data = data;
493
+ uv_async_send (async_handle);
355
494
}
356
495
357
496
void CallOnComplete (Local<Value> answer,
0 commit comments