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 <stdlib.h> 24#include <stdio.h> 25#include <string.h> 26 27#include "uv.h" 28#include "internal.h" 29 30 31static void uv__getnameinfo_work(struct uv__work* w) { 32 uv_getnameinfo_t* req; 33 int err; 34 socklen_t salen; 35 36 req = container_of(w, uv_getnameinfo_t, work_req); 37 38 if (req->storage.ss_family == AF_INET) 39 salen = sizeof(struct sockaddr_in); 40 else if (req->storage.ss_family == AF_INET6) 41 salen = sizeof(struct sockaddr_in6); 42 else 43 abort(); 44 45 err = getnameinfo((struct sockaddr*) &req->storage, 46 salen, 47 req->host, 48 sizeof(req->host), 49 req->service, 50 sizeof(req->service), 51 req->flags); 52 req->retcode = uv__getaddrinfo_translate_error(err); 53} 54 55static void uv__getnameinfo_done(struct uv__work* w, int status) { 56 uv_getnameinfo_t* req; 57 char* host; 58 char* service; 59 60 req = container_of(w, uv_getnameinfo_t, work_req); 61 uv__req_unregister(req->loop, req); 62 host = service = NULL; 63 64 if (status == UV_ECANCELED) { 65 assert(req->retcode == 0); 66 req->retcode = UV_EAI_CANCELED; 67 } else if (req->retcode == 0) { 68 host = req->host; 69 service = req->service; 70 } 71 72 if (req->getnameinfo_cb) 73 req->getnameinfo_cb(req, req->retcode, host, service); 74} 75 76/* 77* Entry point for getnameinfo 78* return 0 if a callback will be made 79* return error code if validation fails 80*/ 81int uv_getnameinfo(uv_loop_t* loop, 82 uv_getnameinfo_t* req, 83 uv_getnameinfo_cb getnameinfo_cb, 84 const struct sockaddr* addr, 85 int flags) { 86 if (req == NULL || addr == NULL) 87 return UV_EINVAL; 88 89 if (addr->sa_family == AF_INET) { 90 memcpy(&req->storage, 91 addr, 92 sizeof(struct sockaddr_in)); 93 } else if (addr->sa_family == AF_INET6) { 94 memcpy(&req->storage, 95 addr, 96 sizeof(struct sockaddr_in6)); 97 } else { 98 return UV_EINVAL; 99 } 100 101 uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO); 102 103 req->getnameinfo_cb = getnameinfo_cb; 104 req->flags = flags; 105 req->type = UV_GETNAMEINFO; 106 req->loop = loop; 107 req->retcode = 0; 108 109 if (getnameinfo_cb) { 110 uv__work_submit(loop, 111 &req->work_req, 112 UV__WORK_SLOW_IO, 113 uv__getnameinfo_work, 114 uv__getnameinfo_done); 115 return 0; 116 } else { 117 uv__getnameinfo_work(&req->work_req); 118 uv__getnameinfo_done(&req->work_req, 0); 119 return req->retcode; 120 } 121} 122