xref: /third_party/node/deps/uv/src/win/getnameinfo.c (revision 1cb0ef41)
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
30int 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
41static void uv__getnameinfo_work(struct uv__work* w) {
42  uv_getnameinfo_t* req;
43  WCHAR host[NI_MAXHOST];
44  WCHAR service[NI_MAXSERV];
45  int ret;
46
47  req = container_of(w, uv_getnameinfo_t, work_req);
48  if (GetNameInfoW((struct sockaddr*)&req->storage,
49                   sizeof(req->storage),
50                   host,
51                   ARRAY_SIZE(host),
52                   service,
53                   ARRAY_SIZE(service),
54                   req->flags)) {
55    ret = WSAGetLastError();
56    req->retcode = uv__getaddrinfo_translate_error(ret);
57    return;
58  }
59
60  ret = WideCharToMultiByte(CP_UTF8,
61                            0,
62                            host,
63                            -1,
64                            req->host,
65                            sizeof(req->host),
66                            NULL,
67                            NULL);
68  if (ret == 0) {
69    req->retcode = uv_translate_sys_error(GetLastError());
70    return;
71  }
72
73  ret = WideCharToMultiByte(CP_UTF8,
74                            0,
75                            service,
76                            -1,
77                            req->service,
78                            sizeof(req->service),
79                            NULL,
80                            NULL);
81  if (ret == 0) {
82    req->retcode = uv_translate_sys_error(GetLastError());
83  }
84}
85
86
87/*
88* Called from uv_run when complete.
89*/
90static void uv__getnameinfo_done(struct uv__work* w, int status) {
91  uv_getnameinfo_t* req;
92  char* host;
93  char* service;
94
95  req = container_of(w, uv_getnameinfo_t, work_req);
96  uv__req_unregister(req->loop, req);
97  host = service = NULL;
98
99  if (status == UV_ECANCELED) {
100    assert(req->retcode == 0);
101    req->retcode = UV_EAI_CANCELED;
102  } else if (req->retcode == 0) {
103    host = req->host;
104    service = req->service;
105  }
106
107  if (req->getnameinfo_cb)
108    req->getnameinfo_cb(req, req->retcode, host, service);
109}
110
111
112/*
113* Entry point for getnameinfo
114* return 0 if a callback will be made
115* return error code if validation fails
116*/
117int uv_getnameinfo(uv_loop_t* loop,
118                   uv_getnameinfo_t* req,
119                   uv_getnameinfo_cb getnameinfo_cb,
120                   const struct sockaddr* addr,
121                   int flags) {
122  if (req == NULL || addr == NULL)
123    return UV_EINVAL;
124
125  if (addr->sa_family == AF_INET) {
126    memcpy(&req->storage,
127           addr,
128           sizeof(struct sockaddr_in));
129  } else if (addr->sa_family == AF_INET6) {
130    memcpy(&req->storage,
131           addr,
132           sizeof(struct sockaddr_in6));
133  } else {
134    return UV_EINVAL;
135  }
136
137  UV_REQ_INIT(req, UV_GETNAMEINFO);
138  uv__req_register(loop, req);
139
140  req->getnameinfo_cb = getnameinfo_cb;
141  req->flags = flags;
142  req->loop = loop;
143  req->retcode = 0;
144
145  if (getnameinfo_cb) {
146    uv__work_submit(loop,
147                    &req->work_req,
148                    UV__WORK_SLOW_IO,
149                    uv__getnameinfo_work,
150                    uv__getnameinfo_done);
151    return 0;
152  } else {
153    uv__getnameinfo_work(&req->work_req);
154    uv__getnameinfo_done(&req->work_req, 0);
155    return req->retcode;
156  }
157}
158