xref: /third_party/libuv/src/win/getnameinfo.c (revision e66f31c5)
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  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*/
79static 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, req);
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*/
106int 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, req);
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