Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
windows, unix: getnameinfo implementation for #852
Browse files Browse the repository at this point in the history
Address to name translation using getnameinfo. The implementation adds
new public function uv_getnameinfo with support for IPv4 and IPv6.
Two basic tests are provided in test-getnameinfo for IPv4 and IPv6.
  • Loading branch information
zerhacken committed May 16, 2014
1 parent 1579788 commit b772cc3
Show file tree
Hide file tree
Showing 12 changed files with 399 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ libuv_la_SOURCES += src/win/async.c \
src/win/fs-event.c \
src/win/fs.c \
src/win/getaddrinfo.c \
src/win/getnameinfo.c \
src/win/handle.c \
src/win/handle-inl.h \
src/win/internal.h \
Expand Down Expand Up @@ -86,6 +87,7 @@ libuv_la_SOURCES += src/unix/async.c \
src/unix/dl.c \
src/unix/fs.c \
src/unix/getaddrinfo.c \
src/unix/getnameinfo.c \
src/unix/internal.h \
src/unix/loop-watcher.c \
src/unix/loop.c \
Expand Down Expand Up @@ -138,6 +140,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-get-loadavg.c \
test/test-get-memory.c \
test/test-getaddrinfo.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-hrtime.c \
test/test-idle.c \
Expand Down
9 changes: 9 additions & 0 deletions include/uv-unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,15 @@ typedef struct {
struct addrinfo* res; \
int retcode;

#define UV_GETNAMEINFO_PRIVATE_FIELDS \
struct uv__work work_req; \
uv_getnameinfo_cb getnameinfo_cb; \
struct sockaddr_storage storage; \
int flags; \
char host[NI_MAXHOST]; \
char service[NI_MAXSERV]; \
int retcode;

#define UV_PROCESS_PRIVATE_FIELDS \
void* queue[2]; \
int status; \
Expand Down
8 changes: 8 additions & 0 deletions include/uv-win.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,14 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
struct addrinfoW* res; \
int retcode;

#define UV_GETNAMEINFO_PRIVATE_FIELDS \
uv_getnameinfo_cb getnameinfo_cb; \
struct sockaddr_storage storage; \
int flags; \
char host[NI_MAXHOST]; \
char service[NI_MAXSERV]; \
int retcode;

#define UV_PROCESS_PRIVATE_FIELDS \
struct uv_process_exit_s { \
UV_REQ_FIELDS \
Expand Down
34 changes: 34 additions & 0 deletions include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ extern "C" {
XX(FS, fs) \
XX(WORK, work) \
XX(GETADDRINFO, getaddrinfo) \
XX(GETNAMEINFO, getnameinfo) \

typedef enum {
#define XX(code, _) UV_ ## code = UV__ ## code,
Expand Down Expand Up @@ -216,6 +217,7 @@ typedef struct uv_signal_s uv_signal_t;
/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
Expand Down Expand Up @@ -419,6 +421,10 @@ typedef void (*uv_after_work_cb)(uv_work_t* req, int status);
typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req,
int status,
struct addrinfo* res);
typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
int status,
char* hostname,
char* service);

typedef struct {
long tv_sec;
Expand Down Expand Up @@ -1451,6 +1457,33 @@ UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop,
UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);


/*
* uv_getnameinfo_t is a subclass of uv_req_t
*
* Request object for uv_getnameinfo.
*/
struct uv_getnameinfo_s {
UV_REQ_FIELDS
/* read-only */
uv_loop_t* loop;
UV_GETNAMEINFO_PRIVATE_FIELDS
};

/*
* Asynchronous getnameinfo.
*
* Returns 0 on success or an error code < 0 on failure.
*
* If successful, your callback gets called sometime in the future with the
* lookup result.
*/
UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,
uv_getnameinfo_t* req,
uv_getnameinfo_cb getnameinfo_cb,
const struct sockaddr* addr,
int flags);


/* uv_spawn() options */
typedef enum {
UV_IGNORE = 0x00,
Expand Down Expand Up @@ -2252,6 +2285,7 @@ struct uv_loop_s {
#undef UV_ASYNC_PRIVATE_FIELDS
#undef UV_TIMER_PRIVATE_FIELDS
#undef UV_GETADDRINFO_PRIVATE_FIELDS
#undef UV_GETNAMEINFO_PRIVATE_FIELDS
#undef UV_FS_REQ_PRIVATE_FIELDS
#undef UV_WORK_PRIVATE_FIELDS
#undef UV_FS_EVENT_PRIVATE_FIELDS
Expand Down
103 changes: 103 additions & 0 deletions src/unix/getnameinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* 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 <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>

#include "uv.h"
#include "internal.h"


static void uv__getnameinfo_work(struct uv__work* w) {
uv_getnameinfo_t* req;
int err;

req = container_of(w, uv_getnameinfo_t, work_req);
err = getnameinfo((struct sockaddr*)&req->storage,
sizeof(req->storage),
req->host,
sizeof(req->host),
req->service,
sizeof(req->service),
req->flags);
req->retcode = err;
}

static void uv__getnameinfo_done(struct uv__work* w, int status) {
uv_getnameinfo_t* req;
char* host;
char* service;

req = container_of(w, uv_getnameinfo_t, work_req);
uv__req_unregister(req->loop, req);

if (req->retcode == 0) {
host = req->host;
service = req->service;
} else {
host = NULL;
service = NULL;
}

req->getnameinfo_cb(req, req->retcode, host, service);
}

/*
* Entry point for getnameinfo
* return 0 if a callback will be made
* return error code if validation fails
*/
int uv_getnameinfo(uv_loop_t* loop,
uv_getnameinfo_t* req,
uv_getnameinfo_cb getnameinfo_cb,
const struct sockaddr* addr,
int flags) {
if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
return UV_EINVAL;

if (addr->sa_family == AF_INET) {
memcpy(&req->storage,
addr,
sizeof(struct sockaddr_in));
} else if (addr->sa_family == AF_INET6) {
memcpy(&req->storage,
addr,
sizeof(struct sockaddr_in6));
} else {
return UV_EINVAL;
}

uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO);

req->getnameinfo_cb = getnameinfo_cb;
req->flags = flags;
req->type = UV_GETNAMEINFO;
req->loop = loop;

uv__work_submit(loop,
&req->work_req,
uv__getnameinfo_work,
uv__getnameinfo_done);

return 0;
}
4 changes: 4 additions & 0 deletions src/unix/threadpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ int uv_cancel(uv_req_t* req) {
loop = ((uv_getaddrinfo_t*) req)->loop;
wreq = &((uv_getaddrinfo_t*) req)->work_req;
break;
case UV_GETNAMEINFO:
loop = ((uv_getnameinfo_t*) req)->loop;
wreq = &((uv_getnameinfo_t*) req)->work_req;
break;
case UV_WORK:
loop = ((uv_work_t*) req)->loop;
wreq = &((uv_work_t*) req)->work_req;
Expand Down
138 changes: 138 additions & 0 deletions src/win/getnameinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* 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 <assert.h>
#include <malloc.h>
#include <stdio.h>

#include "uv.h"
#include "internal.h"
#include "req-inl.h"


/* getnameinfo worker thread implementation */
static DWORD WINAPI getnameinfo_thread_proc(void* parameter) {
uv_getnameinfo_t* req = (uv_getnameinfo_t*)parameter;
uv_loop_t* loop = req->loop;
WCHAR host[NI_MAXHOST];
WCHAR service[NI_MAXSERV];
int ret = 0;

assert(req != NULL);

ret = GetNameInfoW((struct sockaddr*)&req->storage,
sizeof(req->storage),
host,
sizeof(host),
service,
sizeof(service),
req->flags);
req->retcode = ret;

/* convert results to UTF-8 */
WideCharToMultiByte(CP_UTF8,
0,
host,
-1,
req->host,
sizeof(req->host),
NULL,
NULL);

WideCharToMultiByte(CP_UTF8,
0,
service,
-1,
req->service,
sizeof(req->service),
NULL,
NULL);

/* post getnameinfo completed */
POST_COMPLETION_FOR_REQ(loop, req);

return 0;
}


/*
* Called from uv_run when complete.
*/
void uv_process_getnameinfo_req(uv_loop_t* loop, uv_getnameinfo_t* req) {
char* host;
char* service;

if (req->retcode == 0) {
host = req->host;
service = req->service;
} else {
host = NULL;
service = NULL;
}

uv__req_unregister(loop, req);
req->getnameinfo_cb(req, req->retcode, host, service);
}


/*
* Entry point for getnameinfo
* return 0 if a callback will be made
* return error code if validation fails
*/
int uv_getnameinfo(uv_loop_t* loop,
uv_getnameinfo_t* req,
uv_getnameinfo_cb getnameinfo_cb,
const struct sockaddr* addr,
int flags) {
if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
return UV_EINVAL;

if (addr->sa_family == AF_INET) {
memcpy(&req->storage,
addr,
sizeof(struct sockaddr_in));
} else if (addr->sa_family == AF_INET6) {
memcpy(&req->storage,
addr,
sizeof(struct sockaddr_in6));
} else {
return UV_EINVAL;
}

uv_req_init(loop, (uv_req_t*)req);

req->getnameinfo_cb = getnameinfo_cb;
req->flags = flags;
req->type = UV_GETNAMEINFO;
req->loop = loop;

/* Ask thread to run. Treat this as a long operation. */
if (QueueUserWorkItem(&getnameinfo_thread_proc,
req,
WT_EXECUTELONGFUNCTION) == 0) {
return uv_translate_sys_error(GetLastError());
}

uv__req_register(loop, req);

return 0;
}
6 changes: 6 additions & 0 deletions src/win/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ int uv_translate_sys_error(int sys_errno);
void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req);


/*
* Getnameinfo
*/
void uv_process_getnameinfo_req(uv_loop_t* loop, uv_getnameinfo_t* req);


/*
* FS
*/
Expand Down
Loading

0 comments on commit b772cc3

Please sign in to comment.