1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22 #include <assert.h>
23 #include <stdio.h>
24
25 #include "uv.h"
26 #include "internal.h"
27 #include "req-inl.h"
28
29 #ifndef GetNameInfo
30 int WSAAPI GetNameInfoW(
31 const SOCKADDR *pSockaddr,
32 socklen_t SockaddrLength,
33 PWCHAR pNodeBuffer,
34 DWORD NodeBufferSize,
35 PWCHAR pServiceBuffer,
36 DWORD ServiceBufferSize,
37 INT Flags
38 );
39 #endif
40
uv__getnameinfo_work(struct uv__work * w)41 static void uv__getnameinfo_work(struct uv__work* w) {
42 uv_getnameinfo_t* req;
43 WCHAR host[NI_MAXHOST];
44 WCHAR service[NI_MAXSERV];
45 size_t size;
46 int ret;
47
48 req = container_of(w, uv_getnameinfo_t, work_req);
49 if (GetNameInfoW((struct sockaddr*)&req->storage,
50 sizeof(req->storage),
51 host,
52 ARRAY_SIZE(host),
53 service,
54 ARRAY_SIZE(service),
55 req->flags)) {
56 ret = WSAGetLastError();
57 req->retcode = uv__getaddrinfo_translate_error(ret);
58 return;
59 }
60
61 size = sizeof(req->host);
62 ret = uv__copy_utf16_to_utf8(host, -1, req->host, &size);
63 if (ret < 0) {
64 req->retcode = ret;
65 return;
66 }
67
68 size = sizeof(req->service);
69 ret = uv__copy_utf16_to_utf8(service, -1, req->service, &size);
70 if (ret < 0) {
71 req->retcode = ret;
72 }
73 }
74
75
76 /*
77 * Called from uv_run when complete.
78 */
uv__getnameinfo_done(struct uv__work * w,int status)79 static void uv__getnameinfo_done(struct uv__work* w, int status) {
80 uv_getnameinfo_t* req;
81 char* host;
82 char* service;
83
84 req = container_of(w, uv_getnameinfo_t, work_req);
85 uv__req_unregister(req->loop);
86 host = service = NULL;
87
88 if (status == UV_ECANCELED) {
89 assert(req->retcode == 0);
90 req->retcode = UV_EAI_CANCELED;
91 } else if (req->retcode == 0) {
92 host = req->host;
93 service = req->service;
94 }
95
96 if (req->getnameinfo_cb)
97 req->getnameinfo_cb(req, req->retcode, host, service);
98 }
99
100
101 /*
102 * Entry point for getnameinfo
103 * return 0 if a callback will be made
104 * return error code if validation fails
105 */
uv_getnameinfo(uv_loop_t * loop,uv_getnameinfo_t * req,uv_getnameinfo_cb getnameinfo_cb,const struct sockaddr * addr,int flags)106 int uv_getnameinfo(uv_loop_t* loop,
107 uv_getnameinfo_t* req,
108 uv_getnameinfo_cb getnameinfo_cb,
109 const struct sockaddr* addr,
110 int flags) {
111 if (req == NULL || addr == NULL)
112 return UV_EINVAL;
113
114 if (addr->sa_family == AF_INET) {
115 memcpy(&req->storage,
116 addr,
117 sizeof(struct sockaddr_in));
118 } else if (addr->sa_family == AF_INET6) {
119 memcpy(&req->storage,
120 addr,
121 sizeof(struct sockaddr_in6));
122 } else {
123 return UV_EINVAL;
124 }
125
126 UV_REQ_INIT(req, UV_GETNAMEINFO);
127 uv__req_register(loop);
128
129 req->getnameinfo_cb = getnameinfo_cb;
130 req->flags = flags;
131 req->loop = loop;
132 req->retcode = 0;
133
134 if (getnameinfo_cb) {
135 uv__work_submit(loop,
136 &req->work_req,
137 UV__WORK_SLOW_IO,
138 uv__getnameinfo_work,
139 uv__getnameinfo_done);
140 return 0;
141 } else {
142 uv__getnameinfo_work(&req->work_req);
143 uv__getnameinfo_done(&req->work_req, 0);
144 return req->retcode;
145 }
146 }
147