#include <assert.h>
#include <stdlib.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;
socklen_t salen;
req = container_of(w, uv_getnameinfo_t, work_req);
if
(req->storage.ss_family == AF_INET)
salen =
sizeof
(
struct
sockaddr_in);
else
if
(req->storage.ss_family == AF_INET6)
salen =
sizeof
(
struct
sockaddr_in6);
else
abort
();
err = getnameinfo((
struct
sockaddr*) &req->storage,
salen,
req->host,
sizeof
(req->host),
req->service,
sizeof
(req->service),
req->flags);
req->retcode = uv__getaddrinfo_translate_error(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);
host = service = NULL;
if
(status == UV_ECANCELED) {
assert
(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
}
else
if
(req->retcode == 0) {
host = req->host;
service = req->service;
}
if
(req->getnameinfo_cb)
req->getnameinfo_cb(req, req->retcode, host, service);
}
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 || 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;
req->retcode = 0;
if
(getnameinfo_cb) {
uv__work_submit(loop,
&req->work_req,
UV__WORK_SLOW_IO,
uv__getnameinfo_work,
uv__getnameinfo_done);
return
0;
}
else
{
uv__getnameinfo_work(&req->work_req);
uv__getnameinfo_done(&req->work_req, 0);
return
req->retcode;
}
}