|
Packit |
b5b901 |
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
Packit |
b5b901 |
*
|
|
Packit |
b5b901 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
b5b901 |
* of this software and associated documentation files (the "Software"), to
|
|
Packit |
b5b901 |
* deal in the Software without restriction, including without limitation the
|
|
Packit |
b5b901 |
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
Packit |
b5b901 |
* sell copies of the Software, and to permit persons to whom the Software is
|
|
Packit |
b5b901 |
* furnished to do so, subject to the following conditions:
|
|
Packit |
b5b901 |
*
|
|
Packit |
b5b901 |
* The above copyright notice and this permission notice shall be included in
|
|
Packit |
b5b901 |
* all copies or substantial portions of the Software.
|
|
Packit |
b5b901 |
*
|
|
Packit |
b5b901 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
b5b901 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
b5b901 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit |
b5b901 |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit |
b5b901 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
Packit |
b5b901 |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
Packit |
b5b901 |
* IN THE SOFTWARE.
|
|
Packit |
b5b901 |
*/
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
#include <assert.h>
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
#include "uv.h"
|
|
Packit |
b5b901 |
#include "internal.h"
|
|
Packit |
b5b901 |
#include "req-inl.h"
|
|
Packit Service |
e08953 |
#include "idna.h"
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* EAI_* constants. */
|
|
Packit |
b5b901 |
#include <winsock2.h>
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
|
|
Packit |
b5b901 |
#include <iphlpapi.h>
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
int uv__getaddrinfo_translate_error(int sys_err) {
|
|
Packit |
b5b901 |
switch (sys_err) {
|
|
Packit |
b5b901 |
case 0: return 0;
|
|
Packit |
b5b901 |
case WSATRY_AGAIN: return UV_EAI_AGAIN;
|
|
Packit |
b5b901 |
case WSAEINVAL: return UV_EAI_BADFLAGS;
|
|
Packit |
b5b901 |
case WSANO_RECOVERY: return UV_EAI_FAIL;
|
|
Packit |
b5b901 |
case WSAEAFNOSUPPORT: return UV_EAI_FAMILY;
|
|
Packit |
b5b901 |
case WSA_NOT_ENOUGH_MEMORY: return UV_EAI_MEMORY;
|
|
Packit |
b5b901 |
case WSAHOST_NOT_FOUND: return UV_EAI_NONAME;
|
|
Packit |
b5b901 |
case WSATYPE_NOT_FOUND: return UV_EAI_SERVICE;
|
|
Packit |
b5b901 |
case WSAESOCKTNOSUPPORT: return UV_EAI_SOCKTYPE;
|
|
Packit |
b5b901 |
default: return uv_translate_sys_error(sys_err);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/*
|
|
Packit |
b5b901 |
* MinGW is missing this
|
|
Packit |
b5b901 |
*/
|
|
Packit |
b5b901 |
#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)
|
|
Packit |
b5b901 |
typedef struct addrinfoW {
|
|
Packit |
b5b901 |
int ai_flags;
|
|
Packit |
b5b901 |
int ai_family;
|
|
Packit |
b5b901 |
int ai_socktype;
|
|
Packit |
b5b901 |
int ai_protocol;
|
|
Packit |
b5b901 |
size_t ai_addrlen;
|
|
Packit |
b5b901 |
WCHAR* ai_canonname;
|
|
Packit |
b5b901 |
struct sockaddr* ai_addr;
|
|
Packit |
b5b901 |
struct addrinfoW* ai_next;
|
|
Packit |
b5b901 |
} ADDRINFOW, *PADDRINFOW;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node,
|
|
Packit |
b5b901 |
const WCHAR* service,
|
|
Packit |
b5b901 |
const ADDRINFOW* hints,
|
|
Packit |
b5b901 |
PADDRINFOW* result);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo);
|
|
Packit |
b5b901 |
#endif
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
|
|
Packit |
b5b901 |
* Do we need different versions of this for different architectures? */
|
|
Packit |
b5b901 |
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
#ifndef NDIS_IF_MAX_STRING_SIZE
|
|
Packit |
b5b901 |
#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
|
|
Packit |
b5b901 |
#endif
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
static void uv__getaddrinfo_work(struct uv__work* w) {
|
|
Packit |
b5b901 |
uv_getaddrinfo_t* req;
|
|
Packit |
b5b901 |
struct addrinfoW* hints;
|
|
Packit |
b5b901 |
int err;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
req = container_of(w, uv_getaddrinfo_t, work_req);
|
|
Packit |
b5b901 |
hints = req->addrinfow;
|
|
Packit |
b5b901 |
req->addrinfow = NULL;
|
|
Packit |
b5b901 |
err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
|
|
Packit |
b5b901 |
req->retcode = uv__getaddrinfo_translate_error(err);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/*
|
|
Packit |
b5b901 |
* Called from uv_run when complete. Call user specified callback
|
|
Packit |
b5b901 |
* then free returned addrinfo
|
|
Packit |
b5b901 |
* Returned addrinfo strings are converted from UTF-16 to UTF-8.
|
|
Packit |
b5b901 |
*
|
|
Packit |
b5b901 |
* To minimize allocation we calculate total size required,
|
|
Packit |
b5b901 |
* and copy all structs and referenced strings into the one block.
|
|
Packit |
b5b901 |
* Each size calculation is adjusted to avoid unaligned pointers.
|
|
Packit |
b5b901 |
*/
|
|
Packit |
b5b901 |
static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
|
Packit |
b5b901 |
uv_getaddrinfo_t* req;
|
|
Packit |
b5b901 |
int addrinfo_len = 0;
|
|
Packit |
b5b901 |
int name_len = 0;
|
|
Packit |
b5b901 |
size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
|
|
Packit |
b5b901 |
struct addrinfoW* addrinfow_ptr;
|
|
Packit |
b5b901 |
struct addrinfo* addrinfo_ptr;
|
|
Packit |
b5b901 |
char* alloc_ptr = NULL;
|
|
Packit |
b5b901 |
char* cur_ptr = NULL;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
req = container_of(w, uv_getaddrinfo_t, work_req);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* release input parameter memory */
|
|
Packit |
b5b901 |
uv__free(req->alloc);
|
|
Packit |
b5b901 |
req->alloc = NULL;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (status == UV_ECANCELED) {
|
|
Packit |
b5b901 |
assert(req->retcode == 0);
|
|
Packit |
b5b901 |
req->retcode = UV_EAI_CANCELED;
|
|
Packit |
b5b901 |
goto complete;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (req->retcode == 0) {
|
|
Packit |
b5b901 |
/* Convert addrinfoW to addrinfo. First calculate required length. */
|
|
Packit |
b5b901 |
addrinfow_ptr = req->addrinfow;
|
|
Packit |
b5b901 |
while (addrinfow_ptr != NULL) {
|
|
Packit |
b5b901 |
addrinfo_len += addrinfo_struct_len +
|
|
Packit |
b5b901 |
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
|
|
Packit |
b5b901 |
if (addrinfow_ptr->ai_canonname != NULL) {
|
|
Packit |
b5b901 |
name_len = WideCharToMultiByte(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
addrinfow_ptr->ai_canonname,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
NULL);
|
|
Packit |
b5b901 |
if (name_len == 0) {
|
|
Packit |
b5b901 |
req->retcode = uv_translate_sys_error(GetLastError());
|
|
Packit |
b5b901 |
goto complete;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
addrinfo_len += ALIGNED_SIZE(name_len);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
addrinfow_ptr = addrinfow_ptr->ai_next;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* allocate memory for addrinfo results */
|
|
Packit |
b5b901 |
alloc_ptr = (char*)uv__malloc(addrinfo_len);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* do conversions */
|
|
Packit |
b5b901 |
if (alloc_ptr != NULL) {
|
|
Packit |
b5b901 |
cur_ptr = alloc_ptr;
|
|
Packit |
b5b901 |
addrinfow_ptr = req->addrinfow;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
while (addrinfow_ptr != NULL) {
|
|
Packit |
b5b901 |
/* copy addrinfo struct data */
|
|
Packit |
b5b901 |
assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
|
|
Packit |
b5b901 |
addrinfo_ptr = (struct addrinfo*)cur_ptr;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_canonname = NULL;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_addr = NULL;
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_next = NULL;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
cur_ptr += addrinfo_struct_len;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* copy sockaddr */
|
|
Packit |
b5b901 |
if (addrinfo_ptr->ai_addrlen > 0) {
|
|
Packit |
b5b901 |
assert(cur_ptr + addrinfo_ptr->ai_addrlen <=
|
|
Packit |
b5b901 |
alloc_ptr + addrinfo_len);
|
|
Packit |
b5b901 |
memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
|
|
Packit |
b5b901 |
cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* convert canonical name to UTF-8 */
|
|
Packit |
b5b901 |
if (addrinfow_ptr->ai_canonname != NULL) {
|
|
Packit |
b5b901 |
name_len = WideCharToMultiByte(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
addrinfow_ptr->ai_canonname,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
NULL);
|
|
Packit |
b5b901 |
assert(name_len > 0);
|
|
Packit |
b5b901 |
assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
|
|
Packit |
b5b901 |
name_len = WideCharToMultiByte(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
addrinfow_ptr->ai_canonname,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
cur_ptr,
|
|
Packit |
b5b901 |
name_len,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
NULL);
|
|
Packit |
b5b901 |
assert(name_len > 0);
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_canonname = cur_ptr;
|
|
Packit |
b5b901 |
cur_ptr += ALIGNED_SIZE(name_len);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
assert(cur_ptr <= alloc_ptr + addrinfo_len);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* set next ptr */
|
|
Packit |
b5b901 |
addrinfow_ptr = addrinfow_ptr->ai_next;
|
|
Packit |
b5b901 |
if (addrinfow_ptr != NULL) {
|
|
Packit |
b5b901 |
addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
req->addrinfo = (struct addrinfo*)alloc_ptr;
|
|
Packit |
b5b901 |
} else {
|
|
Packit |
b5b901 |
req->retcode = UV_EAI_MEMORY;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* return memory to system */
|
|
Packit |
b5b901 |
if (req->addrinfow != NULL) {
|
|
Packit |
b5b901 |
FreeAddrInfoW(req->addrinfow);
|
|
Packit |
b5b901 |
req->addrinfow = NULL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
complete:
|
|
Packit |
b5b901 |
uv__req_unregister(req->loop, req);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* finally do callback with converted result */
|
|
Packit |
b5b901 |
if (req->getaddrinfo_cb)
|
|
Packit |
b5b901 |
req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
void uv_freeaddrinfo(struct addrinfo* ai) {
|
|
Packit |
b5b901 |
char* alloc_ptr = (char*)ai;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* release copied result memory */
|
|
Packit |
b5b901 |
uv__free(alloc_ptr);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/*
|
|
Packit |
b5b901 |
* Entry point for getaddrinfo
|
|
Packit |
b5b901 |
* we convert the UTF-8 strings to UNICODE
|
|
Packit |
b5b901 |
* and save the UNICODE string pointers in the req
|
|
Packit |
b5b901 |
* We also copy hints so that caller does not need to keep memory until the
|
|
Packit |
b5b901 |
* callback.
|
|
Packit |
b5b901 |
* return 0 if a callback will be made
|
|
Packit |
b5b901 |
* return error code if validation fails
|
|
Packit |
b5b901 |
*
|
|
Packit |
b5b901 |
* To minimize allocation we calculate total size required,
|
|
Packit |
b5b901 |
* and copy all structs and referenced strings into the one block.
|
|
Packit |
b5b901 |
* Each size calculation is adjusted to avoid unaligned pointers.
|
|
Packit |
b5b901 |
*/
|
|
Packit |
b5b901 |
int uv_getaddrinfo(uv_loop_t* loop,
|
|
Packit |
b5b901 |
uv_getaddrinfo_t* req,
|
|
Packit |
b5b901 |
uv_getaddrinfo_cb getaddrinfo_cb,
|
|
Packit |
b5b901 |
const char* node,
|
|
Packit |
b5b901 |
const char* service,
|
|
Packit |
b5b901 |
const struct addrinfo* hints) {
|
|
Packit Service |
e08953 |
char hostname_ascii[256];
|
|
Packit |
b5b901 |
int nodesize = 0;
|
|
Packit |
b5b901 |
int servicesize = 0;
|
|
Packit |
b5b901 |
int hintssize = 0;
|
|
Packit |
b5b901 |
char* alloc_ptr = NULL;
|
|
Packit |
b5b901 |
int err;
|
|
Packit Service |
e08953 |
long rc;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (req == NULL || (node == NULL && service == NULL)) {
|
|
Packit |
b5b901 |
return UV_EINVAL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
UV_REQ_INIT(req, UV_GETADDRINFO);
|
|
Packit |
b5b901 |
req->getaddrinfo_cb = getaddrinfo_cb;
|
|
Packit |
b5b901 |
req->addrinfo = NULL;
|
|
Packit |
b5b901 |
req->loop = loop;
|
|
Packit |
b5b901 |
req->retcode = 0;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* calculate required memory size for all input values */
|
|
Packit |
b5b901 |
if (node != NULL) {
|
|
Packit Service |
e08953 |
rc = uv__idna_toascii(node,
|
|
Packit Service |
e08953 |
node + strlen(node),
|
|
Packit Service |
e08953 |
hostname_ascii,
|
|
Packit Service |
e08953 |
hostname_ascii + sizeof(hostname_ascii));
|
|
Packit Service |
e08953 |
if (rc < 0)
|
|
Packit Service |
e08953 |
return rc;
|
|
Packit Service |
e08953 |
nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
|
|
Packit Service |
e08953 |
-1, NULL, 0) * sizeof(WCHAR));
|
|
Packit |
b5b901 |
if (nodesize == 0) {
|
|
Packit |
b5b901 |
err = GetLastError();
|
|
Packit |
b5b901 |
goto error;
|
|
Packit |
b5b901 |
}
|
|
Packit Service |
e08953 |
node = hostname_ascii;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (service != NULL) {
|
|
Packit |
b5b901 |
servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
service,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
0) *
|
|
Packit |
b5b901 |
sizeof(WCHAR));
|
|
Packit |
b5b901 |
if (servicesize == 0) {
|
|
Packit |
b5b901 |
err = GetLastError();
|
|
Packit |
b5b901 |
goto error;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
if (hints != NULL) {
|
|
Packit |
b5b901 |
hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* allocate memory for inputs, and partition it as needed */
|
|
Packit |
b5b901 |
alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
|
|
Packit |
b5b901 |
if (!alloc_ptr) {
|
|
Packit |
b5b901 |
err = WSAENOBUFS;
|
|
Packit |
b5b901 |
goto error;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* save alloc_ptr now so we can free if error */
|
|
Packit |
b5b901 |
req->alloc = (void*)alloc_ptr;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Convert node string to UTF16 into allocated memory and save pointer in the
|
|
Packit |
b5b901 |
* request. */
|
|
Packit |
b5b901 |
if (node != NULL) {
|
|
Packit |
b5b901 |
req->node = (WCHAR*)alloc_ptr;
|
|
Packit |
b5b901 |
if (MultiByteToWideChar(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
node,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
(WCHAR*) alloc_ptr,
|
|
Packit |
b5b901 |
nodesize / sizeof(WCHAR)) == 0) {
|
|
Packit |
b5b901 |
err = GetLastError();
|
|
Packit |
b5b901 |
goto error;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
alloc_ptr += nodesize;
|
|
Packit |
b5b901 |
} else {
|
|
Packit |
b5b901 |
req->node = NULL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Convert service string to UTF16 into allocated memory and save pointer in
|
|
Packit |
b5b901 |
* the req. */
|
|
Packit |
b5b901 |
if (service != NULL) {
|
|
Packit |
b5b901 |
req->service = (WCHAR*)alloc_ptr;
|
|
Packit |
b5b901 |
if (MultiByteToWideChar(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
service,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
(WCHAR*) alloc_ptr,
|
|
Packit |
b5b901 |
servicesize / sizeof(WCHAR)) == 0) {
|
|
Packit |
b5b901 |
err = GetLastError();
|
|
Packit |
b5b901 |
goto error;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
alloc_ptr += servicesize;
|
|
Packit |
b5b901 |
} else {
|
|
Packit |
b5b901 |
req->service = NULL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* copy hints to allocated memory and save pointer in req */
|
|
Packit |
b5b901 |
if (hints != NULL) {
|
|
Packit |
b5b901 |
req->addrinfow = (struct addrinfoW*)alloc_ptr;
|
|
Packit |
b5b901 |
req->addrinfow->ai_family = hints->ai_family;
|
|
Packit |
b5b901 |
req->addrinfow->ai_socktype = hints->ai_socktype;
|
|
Packit |
b5b901 |
req->addrinfow->ai_protocol = hints->ai_protocol;
|
|
Packit |
b5b901 |
req->addrinfow->ai_flags = hints->ai_flags;
|
|
Packit |
b5b901 |
req->addrinfow->ai_addrlen = 0;
|
|
Packit |
b5b901 |
req->addrinfow->ai_canonname = NULL;
|
|
Packit |
b5b901 |
req->addrinfow->ai_addr = NULL;
|
|
Packit |
b5b901 |
req->addrinfow->ai_next = NULL;
|
|
Packit |
b5b901 |
} else {
|
|
Packit |
b5b901 |
req->addrinfow = NULL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
uv__req_register(loop, req);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (getaddrinfo_cb) {
|
|
Packit |
b5b901 |
uv__work_submit(loop,
|
|
Packit |
b5b901 |
&req->work_req,
|
|
Packit |
b5b901 |
UV__WORK_SLOW_IO,
|
|
Packit |
b5b901 |
uv__getaddrinfo_work,
|
|
Packit |
b5b901 |
uv__getaddrinfo_done);
|
|
Packit |
b5b901 |
return 0;
|
|
Packit |
b5b901 |
} else {
|
|
Packit |
b5b901 |
uv__getaddrinfo_work(&req->work_req);
|
|
Packit |
b5b901 |
uv__getaddrinfo_done(&req->work_req, 0);
|
|
Packit |
b5b901 |
return req->retcode;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
error:
|
|
Packit |
b5b901 |
if (req != NULL) {
|
|
Packit |
b5b901 |
uv__free(req->alloc);
|
|
Packit |
b5b901 |
req->alloc = NULL;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
return uv_translate_sys_error(err);
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
|
|
Packit |
b5b901 |
NET_LUID luid;
|
|
Packit |
b5b901 |
wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
|
|
Packit |
b5b901 |
DWORD bufsize;
|
|
Packit |
b5b901 |
int r;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (buffer == NULL || size == NULL || *size == 0)
|
|
Packit |
b5b901 |
return UV_EINVAL;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
r = ConvertInterfaceIndexToLuid(ifindex, &luid);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (r != 0)
|
|
Packit |
b5b901 |
return uv_translate_sys_error(r);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (r != 0)
|
|
Packit |
b5b901 |
return uv_translate_sys_error(r);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Check how much space we need */
|
|
Packit |
b5b901 |
bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (bufsize == 0) {
|
|
Packit |
b5b901 |
return uv_translate_sys_error(GetLastError());
|
|
Packit |
b5b901 |
} else if (bufsize > *size) {
|
|
Packit |
b5b901 |
*size = bufsize;
|
|
Packit |
b5b901 |
return UV_ENOBUFS;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
/* Convert to UTF-8 */
|
|
Packit |
b5b901 |
bufsize = WideCharToMultiByte(CP_UTF8,
|
|
Packit |
b5b901 |
0,
|
|
Packit |
b5b901 |
wname,
|
|
Packit |
b5b901 |
-1,
|
|
Packit |
b5b901 |
buffer,
|
|
Packit |
b5b901 |
*size,
|
|
Packit |
b5b901 |
NULL,
|
|
Packit |
b5b901 |
NULL);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (bufsize == 0)
|
|
Packit |
b5b901 |
return uv_translate_sys_error(GetLastError());
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
*size = bufsize - 1;
|
|
Packit |
b5b901 |
return 0;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
|
|
Packit |
b5b901 |
int r;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (buffer == NULL || size == NULL || *size == 0)
|
|
Packit |
b5b901 |
return UV_EINVAL;
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
r = snprintf(buffer, *size, "%d", ifindex);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (r < 0)
|
|
Packit |
b5b901 |
return uv_translate_sys_error(r);
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
if (r >= (int) *size) {
|
|
Packit |
b5b901 |
*size = r + 1;
|
|
Packit |
b5b901 |
return UV_ENOBUFS;
|
|
Packit |
b5b901 |
}
|
|
Packit |
b5b901 |
|
|
Packit |
b5b901 |
*size = r;
|
|
Packit |
b5b901 |
return 0;
|
|
Packit |
b5b901 |
}
|