unix, win: add synchronous uv_get{addr,name}info
PR-URL: https://github.com/libuv/libuv/pull/156 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Bert Belder <bertbelder@gmail.com>
This commit is contained in:
parent
0b9ee2cf00
commit
f2bb8d394c
@ -39,6 +39,13 @@ Public members
|
||||
Loop that started this getaddrinfo request and where completion will be
|
||||
reported. Readonly.
|
||||
|
||||
.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo
|
||||
|
||||
Pointer to a `struct addrinfo` containing the result. Must be freed by the user
|
||||
with :c:func:`uv_freeaddrinfo`.
|
||||
|
||||
.. versionchanged:: 1.3.0 the field is declared as public.
|
||||
|
||||
.. c:member:: uv_loop_t* uv_getnameinfo_t.loop
|
||||
|
||||
Loop that started this getnameinfo request and where completion will be
|
||||
@ -68,6 +75,9 @@ API
|
||||
|
||||
Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure.
|
||||
|
||||
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
|
||||
in which case the request will run **synchronously**.
|
||||
|
||||
.. c:function:: void uv_freeaddrinfo(struct addrinfo* ai)
|
||||
|
||||
Free the struct addrinfo. Passing NULL is allowed and is a no-op.
|
||||
@ -80,4 +90,7 @@ API
|
||||
callback will get called sometime in the future with the lookup result.
|
||||
Consult `man -s 3 getnameinfo` for more details.
|
||||
|
||||
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
|
||||
in which case the request will run **synchronously**.
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
|
||||
|
||||
@ -326,7 +326,7 @@ typedef struct {
|
||||
struct addrinfo* hints; \
|
||||
char* hostname; \
|
||||
char* service; \
|
||||
struct addrinfo* res; \
|
||||
struct addrinfo* addrinfo; \
|
||||
int retcode;
|
||||
|
||||
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
|
||||
|
||||
@ -565,8 +565,11 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
void* alloc; \
|
||||
WCHAR* node; \
|
||||
WCHAR* service; \
|
||||
struct addrinfoW* hints; \
|
||||
struct addrinfoW* res; \
|
||||
/* The addrinfoW field is used to store a pointer to the hints, and */ \
|
||||
/* later on to store the result of GetAddrInfoW. The final result will */ \
|
||||
/* be converted to struct addrinfo* and stored in the addrinfo field. */ \
|
||||
struct addrinfoW* addrinfow; \
|
||||
struct addrinfo* addrinfo; \
|
||||
int retcode;
|
||||
|
||||
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
|
||||
|
||||
@ -772,6 +772,7 @@ struct uv_getaddrinfo_s {
|
||||
UV_REQ_FIELDS
|
||||
/* read-only */
|
||||
uv_loop_t* loop;
|
||||
/* struct addrinfo* addrinfo is marked as private, but it really isn't. */
|
||||
UV_GETADDRINFO_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
|
||||
@ -99,21 +99,17 @@ static void uv__getaddrinfo_work(struct uv__work* w) {
|
||||
int err;
|
||||
|
||||
req = container_of(w, uv_getaddrinfo_t, work_req);
|
||||
err = getaddrinfo(req->hostname, req->service, req->hints, &req->res);
|
||||
err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo);
|
||||
req->retcode = uv__getaddrinfo_translate_error(err);
|
||||
}
|
||||
|
||||
|
||||
static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
||||
uv_getaddrinfo_t* req;
|
||||
struct addrinfo *res;
|
||||
|
||||
req = container_of(w, uv_getaddrinfo_t, work_req);
|
||||
uv__req_unregister(req->loop, req);
|
||||
|
||||
res = req->res;
|
||||
req->res = NULL;
|
||||
|
||||
/* See initialization in uv_getaddrinfo(). */
|
||||
if (req->hints)
|
||||
free(req->hints);
|
||||
@ -133,7 +129,8 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
||||
req->retcode = UV_EAI_CANCELED;
|
||||
}
|
||||
|
||||
req->cb(req, req->retcode, res);
|
||||
if (req->cb)
|
||||
req->cb(req, req->retcode, req->addrinfo);
|
||||
}
|
||||
|
||||
|
||||
@ -149,7 +146,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
size_t len;
|
||||
char* buf;
|
||||
|
||||
if (req == NULL || cb == NULL || (hostname == NULL && service == NULL))
|
||||
if (req == NULL || (hostname == NULL && service == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
hostname_len = hostname ? strlen(hostname) + 1 : 0;
|
||||
@ -163,7 +160,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
uv__req_init(loop, req, UV_GETADDRINFO);
|
||||
req->loop = loop;
|
||||
req->cb = cb;
|
||||
req->res = NULL;
|
||||
req->addrinfo = NULL;
|
||||
req->hints = NULL;
|
||||
req->service = NULL;
|
||||
req->hostname = NULL;
|
||||
@ -185,12 +182,17 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
if (hostname)
|
||||
req->hostname = memcpy(buf + len, hostname, hostname_len);
|
||||
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getaddrinfo_work,
|
||||
uv__getaddrinfo_done);
|
||||
|
||||
return 0;
|
||||
if (cb) {
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getaddrinfo_work,
|
||||
uv__getaddrinfo_done);
|
||||
return 0;
|
||||
} else {
|
||||
uv__getaddrinfo_work(&req->work_req);
|
||||
uv__getaddrinfo_done(&req->work_req, 0);
|
||||
return req->retcode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -69,7 +69,8 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) {
|
||||
service = req->service;
|
||||
}
|
||||
|
||||
req->getnameinfo_cb(req, req->retcode, host, service);
|
||||
if (req->getnameinfo_cb)
|
||||
req->getnameinfo_cb(req, req->retcode, host, service);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -82,7 +83,7 @@ int uv_getnameinfo(uv_loop_t* loop,
|
||||
uv_getnameinfo_cb getnameinfo_cb,
|
||||
const struct sockaddr* addr,
|
||||
int flags) {
|
||||
if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
|
||||
if (req == NULL || addr == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (addr->sa_family == AF_INET) {
|
||||
@ -105,10 +106,15 @@ int uv_getnameinfo(uv_loop_t* loop,
|
||||
req->loop = loop;
|
||||
req->retcode = 0;
|
||||
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getnameinfo_work,
|
||||
uv__getnameinfo_done);
|
||||
|
||||
return 0;
|
||||
if (getnameinfo_cb) {
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getnameinfo_work,
|
||||
uv__getnameinfo_done);
|
||||
return 0;
|
||||
} else {
|
||||
uv__getnameinfo_work(&req->work_req);
|
||||
uv__getnameinfo_done(&req->work_req, 0);
|
||||
return req->retcode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,10 +77,13 @@ int uv__getaddrinfo_translate_error(int sys_err) {
|
||||
|
||||
static void uv__getaddrinfo_work(struct uv__work* w) {
|
||||
uv_getaddrinfo_t* req;
|
||||
struct addrinfoW* hints;
|
||||
int err;
|
||||
|
||||
req = container_of(w, uv_getaddrinfo_t, work_req);
|
||||
err = GetAddrInfoW(req->node, req->service, req->hints, &req->res);
|
||||
hints = req->addrinfow;
|
||||
req->addrinfow = NULL;
|
||||
err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
|
||||
req->retcode = uv__getaddrinfo_translate_error(err);
|
||||
}
|
||||
|
||||
@ -115,17 +118,13 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
||||
if (status == UV_ECANCELED) {
|
||||
assert(req->retcode == 0);
|
||||
req->retcode = UV_EAI_CANCELED;
|
||||
if (req->res != NULL) {
|
||||
FreeAddrInfoW(req->res);
|
||||
req->res = NULL;
|
||||
}
|
||||
goto complete;
|
||||
}
|
||||
|
||||
if (req->retcode == 0) {
|
||||
/* convert addrinfoW to addrinfo */
|
||||
/* first calculate required length */
|
||||
addrinfow_ptr = req->res;
|
||||
addrinfow_ptr = req->addrinfow;
|
||||
while (addrinfow_ptr != NULL) {
|
||||
addrinfo_len += addrinfo_struct_len +
|
||||
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
|
||||
@ -146,7 +145,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
||||
/* do conversions */
|
||||
if (alloc_ptr != NULL) {
|
||||
cur_ptr = alloc_ptr;
|
||||
addrinfow_ptr = req->res;
|
||||
addrinfow_ptr = req->addrinfow;
|
||||
|
||||
while (addrinfow_ptr != NULL) {
|
||||
/* copy addrinfo struct data */
|
||||
@ -196,22 +195,24 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
||||
addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
|
||||
}
|
||||
}
|
||||
req->addrinfo = (struct addrinfo*)alloc_ptr;
|
||||
} else {
|
||||
req->retcode = UV_EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
complete:
|
||||
/* return memory to system */
|
||||
if (req->res != NULL) {
|
||||
FreeAddrInfoW(req->res);
|
||||
req->res = NULL;
|
||||
if (req->addrinfow != NULL) {
|
||||
FreeAddrInfoW(req->addrinfow);
|
||||
req->addrinfow = NULL;
|
||||
}
|
||||
|
||||
complete:
|
||||
uv__req_unregister(req->loop, req);
|
||||
|
||||
/* finally do callback with converted result */
|
||||
req->getaddrinfo_cb(req, req->retcode, (struct addrinfo*)alloc_ptr);
|
||||
if (req->getaddrinfo_cb)
|
||||
req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
|
||||
}
|
||||
|
||||
|
||||
@ -250,8 +251,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
char* alloc_ptr = NULL;
|
||||
int err;
|
||||
|
||||
if (req == NULL || getaddrinfo_cb == NULL ||
|
||||
(node == NULL && service == NULL)) {
|
||||
if (req == NULL || (node == NULL && service == NULL)) {
|
||||
err = WSAEINVAL;
|
||||
goto error;
|
||||
}
|
||||
@ -259,7 +259,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
uv_req_init(loop, (uv_req_t*)req);
|
||||
|
||||
req->getaddrinfo_cb = getaddrinfo_cb;
|
||||
req->res = NULL;
|
||||
req->addrinfo = NULL;
|
||||
req->type = UV_GETADDRINFO;
|
||||
req->loop = loop;
|
||||
req->retcode = 0;
|
||||
@ -327,27 +327,32 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
|
||||
/* copy hints to allocated memory and save pointer in req */
|
||||
if (hints != NULL) {
|
||||
req->hints = (struct addrinfoW*)alloc_ptr;
|
||||
req->hints->ai_family = hints->ai_family;
|
||||
req->hints->ai_socktype = hints->ai_socktype;
|
||||
req->hints->ai_protocol = hints->ai_protocol;
|
||||
req->hints->ai_flags = hints->ai_flags;
|
||||
req->hints->ai_addrlen = 0;
|
||||
req->hints->ai_canonname = NULL;
|
||||
req->hints->ai_addr = NULL;
|
||||
req->hints->ai_next = NULL;
|
||||
req->addrinfow = (struct addrinfoW*)alloc_ptr;
|
||||
req->addrinfow->ai_family = hints->ai_family;
|
||||
req->addrinfow->ai_socktype = hints->ai_socktype;
|
||||
req->addrinfow->ai_protocol = hints->ai_protocol;
|
||||
req->addrinfow->ai_flags = hints->ai_flags;
|
||||
req->addrinfow->ai_addrlen = 0;
|
||||
req->addrinfow->ai_canonname = NULL;
|
||||
req->addrinfow->ai_addr = NULL;
|
||||
req->addrinfow->ai_next = NULL;
|
||||
} else {
|
||||
req->hints = NULL;
|
||||
req->addrinfow = NULL;
|
||||
}
|
||||
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getaddrinfo_work,
|
||||
uv__getaddrinfo_done);
|
||||
|
||||
uv__req_register(loop, req);
|
||||
|
||||
return 0;
|
||||
if (getaddrinfo_cb) {
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getaddrinfo_work,
|
||||
uv__getaddrinfo_done);
|
||||
return 0;
|
||||
} else {
|
||||
uv__getaddrinfo_work(&req->work_req);
|
||||
uv__getaddrinfo_done(&req->work_req, 0);
|
||||
return req->retcode;
|
||||
}
|
||||
|
||||
error:
|
||||
if (req != NULL && req->alloc != NULL) {
|
||||
|
||||
@ -98,7 +98,8 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) {
|
||||
service = req->service;
|
||||
}
|
||||
|
||||
req->getnameinfo_cb(req, req->retcode, host, service);
|
||||
if (req->getnameinfo_cb)
|
||||
req->getnameinfo_cb(req, req->retcode, host, service);
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +113,7 @@ int uv_getnameinfo(uv_loop_t* loop,
|
||||
uv_getnameinfo_cb getnameinfo_cb,
|
||||
const struct sockaddr* addr,
|
||||
int flags) {
|
||||
if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
|
||||
if (req == NULL || addr == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (addr->sa_family == AF_INET) {
|
||||
@ -136,10 +137,15 @@ int uv_getnameinfo(uv_loop_t* loop,
|
||||
req->loop = loop;
|
||||
req->retcode = 0;
|
||||
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getnameinfo_work,
|
||||
uv__getnameinfo_done);
|
||||
|
||||
return 0;
|
||||
if (getnameinfo_cb) {
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
uv__getnameinfo_work,
|
||||
uv__getnameinfo_done);
|
||||
return 0;
|
||||
} else {
|
||||
uv__getnameinfo_work(&req->work_req);
|
||||
uv__getnameinfo_done(&req->work_req, 0);
|
||||
return req->retcode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,6 +97,22 @@ TEST_IMPL(getaddrinfo_fail) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_fail_sync) {
|
||||
uv_getaddrinfo_t req;
|
||||
|
||||
ASSERT(0 > uv_getaddrinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
"xyzzy.xyzzy.xyzzy",
|
||||
NULL,
|
||||
NULL));
|
||||
uv_freeaddrinfo(req.addrinfo);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_basic) {
|
||||
int r;
|
||||
getaddrinfo_handle = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t));
|
||||
@ -118,6 +134,22 @@ TEST_IMPL(getaddrinfo_basic) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_basic_sync) {
|
||||
uv_getaddrinfo_t req;
|
||||
|
||||
ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
name,
|
||||
NULL,
|
||||
NULL));
|
||||
uv_freeaddrinfo(req.addrinfo);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getaddrinfo_concurrent) {
|
||||
int i, r;
|
||||
int* data;
|
||||
|
||||
@ -44,6 +44,7 @@ static void getnameinfo_req(uv_getnameinfo_t* handle,
|
||||
ASSERT(service != NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip4) {
|
||||
int r;
|
||||
|
||||
@ -63,6 +64,23 @@ TEST_IMPL(getnameinfo_basic_ip4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip4_sync) {
|
||||
ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4));
|
||||
|
||||
ASSERT(0 == uv_getnameinfo(uv_default_loop(),
|
||||
&req,
|
||||
NULL,
|
||||
(const struct sockaddr*)&addr4,
|
||||
0));
|
||||
ASSERT(req.host != NULL);
|
||||
ASSERT(req.service != NULL);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getnameinfo_basic_ip6) {
|
||||
int r;
|
||||
|
||||
|
||||
@ -180,9 +180,12 @@ TEST_DECLARE (get_memory)
|
||||
TEST_DECLARE (handle_fileno)
|
||||
TEST_DECLARE (hrtime)
|
||||
TEST_DECLARE (getaddrinfo_fail)
|
||||
TEST_DECLARE (getaddrinfo_fail_sync)
|
||||
TEST_DECLARE (getaddrinfo_basic)
|
||||
TEST_DECLARE (getaddrinfo_basic_sync)
|
||||
TEST_DECLARE (getaddrinfo_concurrent)
|
||||
TEST_DECLARE (getnameinfo_basic_ip4)
|
||||
TEST_DECLARE (getnameinfo_basic_ip4_sync)
|
||||
TEST_DECLARE (getnameinfo_basic_ip6)
|
||||
TEST_DECLARE (getsockname_tcp)
|
||||
TEST_DECLARE (getsockname_udp)
|
||||
@ -524,11 +527,14 @@ TASK_LIST_START
|
||||
TEST_ENTRY (hrtime)
|
||||
|
||||
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
|
||||
TEST_ENTRY (getaddrinfo_fail_sync)
|
||||
|
||||
TEST_ENTRY (getaddrinfo_basic)
|
||||
TEST_ENTRY (getaddrinfo_basic_sync)
|
||||
TEST_ENTRY (getaddrinfo_concurrent)
|
||||
|
||||
TEST_ENTRY (getnameinfo_basic_ip4)
|
||||
TEST_ENTRY (getnameinfo_basic_ip4_sync)
|
||||
TEST_ENTRY (getnameinfo_basic_ip6)
|
||||
|
||||
TEST_ENTRY (getsockname_tcp)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user