Windows: getaddrinfo support

This commit is contained in:
Henry Rawas 2011-06-23 01:29:50 +02:00 committed by Bert Belder
parent af15cbe6e9
commit 295fa6f538
11 changed files with 646 additions and 3 deletions

View File

@ -136,6 +136,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\test\benchmark-ares.c" />
<ClCompile Include="..\test\benchmark-getaddrinfo.c" />
<ClCompile Include="..\test\benchmark-ping-pongs.c" />
<ClCompile Include="..\test\benchmark-pump.c" />
<ClCompile Include="..\test\benchmark-sizes.c" />

View File

@ -150,6 +150,7 @@
<ClCompile Include="..\test\test-get-currentexe.c" />
<ClCompile Include="..\test\test-fail-always.c" />
<ClCompile Include="..\test\test-gethostbyname.c" />
<ClCompile Include="..\test\test-getaddrinfo.c" />
<ClCompile Include="..\test\test-hrtime.c" />
<ClCompile Include="..\test\test-loop-handles.c" />
<ClCompile Include="..\test\test-pass-always.c" />

View File

@ -0,0 +1,96 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* strlen */
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
/* data used for running multiple calls concurrently */
#define CONCURRENT_COUNT 1000
int callback_counts[CONCURRENT_COUNT];
uv_getaddrinfo_t getaddrinfo_handles[CONCURRENT_COUNT];
static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle, int status, struct addrinfo* res) {
int i;
for (i = 0; i < CONCURRENT_COUNT; i++) {
if (&getaddrinfo_handles[i] == handle) {
callback_counts[i]++;
break;
}
}
ASSERT (i < CONCURRENT_COUNT);
}
static int64_t start_time;
static int64_t end_time;
BENCHMARK_IMPL(getaddrinfo) {
int rc = 0;
char* name = "localhost";
int i;
uv_init();
uv_update_time();
start_time = uv_now();
for (i = 0; i < CONCURRENT_COUNT; i++) {
callback_counts[i] = 0;
uv_getaddrinfo(&getaddrinfo_handles[i],
&getaddrinfo_cuncurrent_cb,
name,
NULL,
NULL);
}
uv_run();
end_time = uv_now();
for (i = 0; i < CONCURRENT_COUNT; i++) {
if (callback_counts[i] != 1) {
printf("Not all callbacks were called 1 time\n");
}
}
LOGF("getaddrinfo: %d calls in %ld ms \n", CONCURRENT_COUNT, (end_time - start_time));
return 0;
}

View File

@ -24,6 +24,7 @@ BENCHMARK_DECLARE (ping_pongs)
BENCHMARK_DECLARE (pump100_client)
BENCHMARK_DECLARE (pump1_client)
BENCHMARK_DECLARE (gethostbyname)
BENCHMARK_DECLARE (getaddrinfo)
HELPER_DECLARE (pump_server)
HELPER_DECLARE (echo_server)
HELPER_DECLARE (dns_server)
@ -43,4 +44,5 @@ TASK_LIST_START
BENCHMARK_ENTRY (gethostbyname)
BENCHMARK_HELPER (gethostbyname, dns_server)
BENCHMARK_ENTRY (getaddrinfo)
TASK_LIST_END

146
test/test-getaddrinfo.c Normal file
View File

@ -0,0 +1,146 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* strlen */
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
int getaddrinfo_callbacks;
uv_getaddrinfo_t getaddrinfo_handle;
static void getaddrinfo_callback(uv_getaddrinfo_t* handle, int status, struct addrinfo* res) {
ASSERT(handle == &getaddrinfo_handle);
getaddrinfo_callbacks++;
}
/* data used for running multiple calls concurrently */
#define CONCURRENT_COUNT 10
int callback_counts[CONCURRENT_COUNT];
uv_getaddrinfo_t getaddrinfo_handles[CONCURRENT_COUNT];
static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle, int status, struct addrinfo* res) {
int i;
for (i = 0; i < CONCURRENT_COUNT; i++) {
if (&getaddrinfo_handles[i] == handle) {
callback_counts[i]++;
break;
}
}
ASSERT (i < CONCURRENT_COUNT);
}
TEST_IMPL(getaddrinfo) {
int rc = 0;
char* name = "localhost";
int i;
uv_init();
printf("Start basic getaddrinfo test\n");
getaddrinfo_callbacks = 0;
uv_getaddrinfo(&getaddrinfo_handle,
&getaddrinfo_callback,
name,
NULL,
NULL);
uv_run();
ASSERT(getaddrinfo_callbacks == 1);
printf("Done basic getaddrinfo test\n");
printf("Start multiple getaddrinfo sequential test\n");
getaddrinfo_callbacks = 0;
uv_getaddrinfo(&getaddrinfo_handle,
&getaddrinfo_callback,
name,
NULL,
NULL);
uv_run();
ASSERT(getaddrinfo_callbacks == 1);
getaddrinfo_callbacks = 0;
uv_getaddrinfo(&getaddrinfo_handle,
&getaddrinfo_callback,
name,
NULL,
NULL);
uv_run();
ASSERT(getaddrinfo_callbacks == 1);
printf("Done multiple getaddrinfo sequential test test\n");
printf("Start multiple getaddrinfo concurrent test\n");
for (i = 0; i < CONCURRENT_COUNT; i++)
{
callback_counts[i] = 0;
uv_getaddrinfo(&getaddrinfo_handles[i],
&getaddrinfo_cuncurrent_cb,
name,
NULL,
NULL);
}
uv_run();
for (i = 0; i < CONCURRENT_COUNT; i++)
{
ASSERT(callback_counts[i] == 1);
}
printf("Done multiple getaddrinfo concurrent test\n");
return 0;
}

View File

@ -44,6 +44,7 @@ TEST_DECLARE (async)
TEST_DECLARE (get_currentexe)
TEST_DECLARE (hrtime)
TEST_DECLARE (gethostbyname)
TEST_DECLARE (getaddrinfo)
TEST_DECLARE (fail_always)
TEST_DECLARE (pass_always)
HELPER_DECLARE (echo_server)
@ -95,6 +96,7 @@ TASK_LIST_START
TEST_ENTRY (get_currentexe)
TEST_ENTRY (hrtime)
TEST_ENTRY (getaddrinfo)
TEST_ENTRY (gethostbyname)
TEST_HELPER (gethostbyname, echo_server)

View File

@ -1303,3 +1303,21 @@ void uv_ares_destroy(ares_channel channel) {
}
/* temporary implementation of uv_getaddrinfo
* calls getaddrinfo, then invokes callback and frees addrinfo
*/
void uv_getaddrinfo(uv_getaddrinfo_t* handle,
uv_getaddrinfo_cb getaddrinfo_cb,
char* node,
char* service,
struct addrinfo* hints) {
int ret;
struct addrinfo* res = NULL;
ret = getaddrinfo(getaddrinfo_cb, node, service, hints, &res);
/* call user with results */
(*getaddrinfo_cb)(handle, uv_translate_sys_error(ret), res);
if (ret == 0) {
freeaddrinfo(res);
}
}

View File

@ -102,4 +102,6 @@ typedef struct {
#define UV_ARES_TASK_PRIVATE_FIELDS /* TODO */
#define UV_GETADDRINFO_PRIVATE_FIELDS /* TODO */
#endif /* UV_UNIX_H */

332
uv-win.c
View File

@ -106,6 +106,38 @@
#endif
/*
* MinGw is missing this too
*/
#ifndef _MSC_VER
typedef struct addrinfoW {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
wchar_t* ai_canonname;
struct sockaddr* ai_addr;
struct addrinfoW* ai_next;
} ADDRINFOW, *PADDRINFOW;
DECLSPEC_IMPORT
int
WSAAPI
GetAddrInfoW(const wchar_t* node,
const wchar_t* service,
const ADDRINFOW* hints,
PADDRINFOW* result);
DECLSPEC_IMPORT
void
WSAAPI
FreeAddrInfoW(PADDRINFOW pAddrInfo);
#endif
/*
* Pointers to winsock extension functions to be retrieved dynamically
*/
@ -210,6 +242,13 @@ static uv_ares_channel_t uv_ares_data = { NULL };
#define ARES_TIMEOUT_MS 20000
/* getaddrinfo integration */
static void uv_getaddrinfo_done(uv_getaddrinfo_t* handle, uv_req_t* req);
/* adjust size value to be multiple of 4. Use to keep pointer aligned */
/* Do we need different versions of this for different architectures? */
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
/* Atomic set operation on char */
#ifdef _MSC_VER /* MSVC */
@ -313,6 +352,10 @@ static uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE;
case WSAEMFILE: return UV_EMFILE;
case ERROR_OUTOFMEMORY: return UV_ENOMEM;
case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL;
case ERROR_INVALID_FLAGS: return UV_EBADF;
case ERROR_INVALID_PARAMETER: return UV_EINVAL;
case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
default: return UV_UNKNOWN;
}
}
@ -1546,6 +1589,10 @@ static void uv_process_reqs() {
uv_ares_task_cleanup((uv_ares_task_t*)handle, req);
break;
case UV_GETADDRINFO:
uv_getaddrinfo_done((uv_getaddrinfo_t*)handle, req);
break;
default:
assert(0);
}
@ -1690,6 +1737,10 @@ int uv_utf16_to_utf8(wchar_t* utf16Buffer, size_t utf16Size, char* utf8Buffer, s
return WideCharToMultiByte(CP_UTF8, 0, utf16Buffer, utf16Size, utf8Buffer, utf8Size, NULL, NULL);
}
int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer, size_t utf16Size) {
return MultiByteToWideChar(CP_UTF8, 0, utf8Buffer, -1, utf16Buffer, utf16Size);
}
int uv_get_exepath(char* buffer, size_t* size) {
int retVal;
@ -2000,3 +2051,284 @@ void uv_ares_destroy(ares_channel channel) {
}
/*
* getaddrinfo error code mapping
* Falls back to uv_translate_sys_error if no match
*/
static uv_err_code uv_translate_eai_error(int eai_errno) {
switch (eai_errno) {
case ERROR_SUCCESS: return UV_OK;
case EAI_BADFLAGS: return UV_EBADF;
case EAI_FAIL: return UV_EFAULT;
case EAI_FAMILY: return UV_EAIFAMNOSUPPORT;
case EAI_MEMORY: return UV_ENOMEM;
case EAI_NONAME: return UV_EAINONAME;
case EAI_AGAIN: return UV_EAGAIN;
case EAI_SERVICE: return UV_EAISERVICE;
case EAI_SOCKTYPE: return UV_EAISOCKTYPE;
default: return uv_translate_sys_error(eai_errno);
}
}
/* getaddrinfo worker thread implementation */
static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
uv_getaddrinfo_t* handle = (uv_getaddrinfo_t*)parameter;
int ret;
assert(handle != NULL);
if (handle != NULL) {
/* call OS function on this thread */
ret = GetAddrInfoW(handle->node, handle->service, handle->hints, &handle->res);
handle->retcode = ret;
/* post getaddrinfo completed */
if (!PostQueuedCompletionStatus(uv_iocp_,
0,
0,
&handle->getadddrinfo_req.overlapped)) {
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
}
}
return 0;
}
/*
* Called from uv_run when complete. Call user specified callback
* then free returned addrinfo
* Returned addrinfo strings are converted from UTF-16 to UTF-8.
*
* To minimize allocation we calculate total size required,
* and copy all structs and referenced strings into the one block.
* Each size calculation is adjusted to avoid unaligned pointers.
*/
static void uv_getaddrinfo_done(uv_getaddrinfo_t* handle, uv_req_t* req) {
int addrinfo_len = 0;
int name_len = 0;
size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
struct addrinfoW* addrinfow_ptr;
struct addrinfo* addrinfo_ptr;
char* alloc_ptr = NULL;
char* cur_ptr = NULL;
uv_err_code uv_ret;
/* release input parameter memory */
if (handle->alloc != NULL) {
free(handle->alloc);
handle->alloc = NULL;
}
uv_ret = uv_translate_eai_error(handle->retcode);
if (handle->retcode == 0) {
/* convert addrinfoW to addrinfo */
/* first calculate required length */
addrinfow_ptr = handle->res;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len + ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
if (addrinfow_ptr->ai_canonname != NULL) {
name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0);
if (name_len == 0) {
uv_ret = uv_translate_sys_error(GetLastError());
goto complete;
}
addrinfo_len += ALIGNED_SIZE(name_len);
}
addrinfow_ptr = addrinfow_ptr->ai_next;
}
/* allocate memory for addrinfo results */
alloc_ptr = (char*)malloc(addrinfo_len);
/* do conversions */
if (alloc_ptr != NULL) {
cur_ptr = alloc_ptr;
addrinfow_ptr = handle->res;
while (addrinfow_ptr != NULL) {
/* copy addrinfo struct data */
assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
addrinfo_ptr = (struct addrinfo*)cur_ptr;
addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
addrinfo_ptr->ai_canonname = NULL;
addrinfo_ptr->ai_addr = NULL;
addrinfo_ptr->ai_next = NULL;
cur_ptr += addrinfo_struct_len;
/* copy sockaddr */
if (addrinfo_ptr->ai_addrlen > 0) {
assert(cur_ptr + addrinfo_ptr->ai_addrlen <= alloc_ptr + addrinfo_len);
memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
}
/* convert canonical name to UTF-8 */
if (addrinfow_ptr->ai_canonname != NULL) {
name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0);
assert(name_len > 0);
assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, cur_ptr, name_len);
assert(name_len > 0);
addrinfo_ptr->ai_canonname = cur_ptr;
cur_ptr += ALIGNED_SIZE(name_len);
}
assert(cur_ptr <= alloc_ptr + addrinfo_len);
/* set next ptr */
addrinfow_ptr = addrinfow_ptr->ai_next;
if (addrinfow_ptr != NULL) {
addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
}
}
} else {
uv_ret = UV_ENOMEM;
}
}
/* return memory to system */
if (handle->res != NULL) {
FreeAddrInfoW(handle->res);
handle->res = NULL;
}
complete:
/* finally do callback with converted result */
handle->getaddrinfo_cb(handle, uv_ret, (struct addrinfo*)alloc_ptr);
/* release copied result memory */
if (alloc_ptr != NULL) {
free(alloc_ptr);
}
uv_refs_--;
}
/*
* Entry point for getaddrinfo
* we convert the UTF-8 strings to UNICODE
* and save the UNICODE string pointers in the handle
* We also copy hints so that caller does not need to keep memory until the callback.
* return UV_OK if a callback will be made
* return error code if validation fails
*
* To minimize allocation we calculate total size required,
* and copy all structs and referenced strings into the one block.
* Each size calculation is adjusted to avoid unaligned pointers.
*/
uv_err_code uv_getaddrinfo(uv_getaddrinfo_t* handle,
uv_getaddrinfo_cb getaddrinfo_cb,
const char* node,
const char* service,
const struct addrinfo* hints) {
uv_err_code ret = UV_OK;
int nodesize = 0;
int servicesize = 0;
int hintssize = 0;
char* alloc_ptr = NULL;
if (handle == NULL || getaddrinfo_cb == NULL ||
(node == NULL && service == NULL)) {
ret = UV_EINVAL;
goto error;
}
handle->getaddrinfo_cb = getaddrinfo_cb;
handle->res = NULL;
handle->type = UV_GETADDRINFO;
/* calculate required memory size for all input values */
if (node != NULL) {
nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(wchar_t));
if (nodesize == 0) {
ret = uv_translate_sys_error(GetLastError());
goto error;
}
}
if (service != NULL) {
servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * sizeof(wchar_t));
if (servicesize == 0) {
ret = uv_translate_sys_error(GetLastError());
goto error;
}
}
if (hints != NULL) {
hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
}
/* allocate memory for inputs, and partition it as needed */
alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize);
if (!alloc_ptr) {
ret = UV_ENOMEM;
goto error;
}
/* save alloc_ptr now so we can free if error */
handle->alloc = (void*)alloc_ptr;
/* convert node string to UTF16 into allocated memory and save pointer in handle */
if (node != NULL) {
handle->node = (wchar_t*)alloc_ptr;
if (uv_utf8_to_utf16(node, (wchar_t*)alloc_ptr, nodesize / sizeof(wchar_t)) == 0) {
ret = uv_translate_sys_error(GetLastError());
goto error;
}
alloc_ptr += nodesize;
} else {
handle->node = NULL;
}
/* convert service string to UTF16 into allocated memory and save pointer in handle */
if (service != NULL) {
handle->service = (wchar_t*)alloc_ptr;
if (uv_utf8_to_utf16(service, (wchar_t*)alloc_ptr, servicesize / sizeof(wchar_t)) == 0) {
ret = uv_translate_sys_error(GetLastError());
goto error;
}
alloc_ptr += servicesize;
} else {
handle->service = NULL;
}
/* copy hints to allocated memory and save pointer in handle */
if (hints != NULL) {
handle->hints = (struct addrinfoW*)alloc_ptr;
handle->hints->ai_family = hints->ai_family;
handle->hints->ai_socktype = hints->ai_socktype;
handle->hints->ai_protocol = hints->ai_protocol;
handle->hints->ai_flags = hints->ai_flags;
handle->hints->ai_addrlen = 0;
handle->hints->ai_canonname = NULL;
handle->hints->ai_addr = NULL;
handle->hints->ai_next = NULL;
} else {
handle->hints = NULL;
}
/* init request for Post handling */
uv_req_init(&handle->getadddrinfo_req, (uv_handle_t*)handle, NULL);
handle->getadddrinfo_req.type = UV_WAKEUP;
/* Ask thread to run. Treat this as a long operation */
if (QueueUserWorkItem(&getaddrinfo_thread_proc, handle, WT_EXECUTELONGFUNCTION) == 0) {
uv_fatal_error(GetLastError(), "QueueUserWorkItem");
}
uv_refs_++;
return UV_OK;
error:
if (handle != NULL && handle->alloc != NULL) {
free(handle->alloc);
}
return ret;
}

View File

@ -31,7 +31,6 @@
#include "tree.h"
/**
* It should be possible to cast uv_buf_t[] to WSABUF[]
* see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx
@ -123,4 +122,16 @@ typedef struct uv_buf_t {
WSAEVENT h_event; \
HANDLE h_close_event;
#define UV_GETADDRINFO_PRIVATE_FIELDS \
struct uv_req_s getadddrinfo_req; \
uv_getaddrinfo_cb getaddrinfo_cb; \
void* alloc; \
wchar_t* node; \
wchar_t* service; \
struct addrinfoW* hints; \
struct addrinfoW* res; \
int retcode;
int uv_utf16_to_utf8(wchar_t* utf16Buffer, size_t utf16Size, char* utf8Buffer, size_t utf8Size);
int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer, size_t utf16Size);

36
uv.h
View File

@ -50,6 +50,7 @@ typedef struct uv_req_s uv_req_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_ares_task_s uv_ares_task_t;
typedef struct uv_ares_action_s uv_ares_action_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)
@ -80,6 +81,7 @@ typedef void (*uv_async_cb)(uv_async_t* handle, int status);
typedef void (*uv_prepare_cb)(uv_prepare_t* handle, int status);
typedef void (*uv_check_cb)(uv_check_t* handle, int status);
typedef void (*uv_idle_cb)(uv_idle_t* handle, int status);
typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* handle, int status, struct addrinfo *res);
/* Expand this list if necessary. */
@ -118,7 +120,12 @@ typedef enum {
UV_EPROTO,
UV_EPROTONOSUPPORT,
UV_EPROTOTYPE,
UV_ETIMEDOUT
UV_ETIMEDOUT,
UV_ECHARSET,
UV_EAIFAMNOSUPPORT,
UV_EAINONAME,
UV_EAISERVICE,
UV_EAISOCKTYPE
} uv_err_code;
typedef enum {
@ -133,7 +140,8 @@ typedef enum {
UV_IDLE,
UV_ASYNC,
UV_ARES,
UV_ARES_TASK
UV_ARES_TASK,
UV_GETADDRINFO
} uv_handle_type;
typedef enum {
@ -393,6 +401,29 @@ int uv_ares_init_options(ares_channel *channelptr,
void uv_ares_destroy(ares_channel channel);
/*
* Subclass of uv_handle_t. Used for integration of getaddrinfo.
*/
struct uv_getaddrinfo_s {
UV_HANDLE_FIELDS
UV_GETADDRINFO_PRIVATE_FIELDS
};
/* uv_getaddrinfo
* return code of UV_OK means that request is accepted,
* and callback will be called with result.
* Other return codes mean that there will not be a callback.
* Input arguments may be released after return from this call.
* Callback must not call freeaddrinfo
*/
uv_err_code uv_getaddrinfo(uv_getaddrinfo_t* handle,
uv_getaddrinfo_cb getaddrinfo_cb,
const char* node,
const char* service,
const struct addrinfo* hints);
/*
* Most functions return boolean: 0 for success and -1 for failure.
* On error the user should then call uv_last_error() to determine
@ -432,6 +463,7 @@ union uv_any_handle {
uv_timer_t timer;
uv_ares_task_t arest;
uv_ares_action_t aresa;
uv_getaddrinfo_t getaddrinfo;
};
/* Diagnostic counters */