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 31 static 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 55 static 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 */ 81 int 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