X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fgetaddrinfo.c;h=2222562afc5032ad3b2ee21d52d554952d210c6b;hb=817e3ec506c4095bc4fcc1923cee36153ef4ee43;hp=4595cc47a041a4ac6f3e1a1775b9edfc866b785e;hpb=a2df84f2250bbe1dc2ac610687e784c73b10e8e9;p=pazpar2-moved-to-github.git diff --git a/src/getaddrinfo.c b/src/getaddrinfo.c index 4595cc4..2222562 100644 --- a/src/getaddrinfo.c +++ b/src/getaddrinfo.c @@ -1,7 +1,5 @@ -/* $Id: getaddrinfo.c,v 1.3 2007-04-23 07:34:48 adam Exp $ - Copyright (c) 2006-2007, Index Data. - -This file is part of Pazpar2. +/* This file is part of Pazpar2. + Copyright (C) Index Data Pazpar2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -14,81 +12,112 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Pazpar2; see the file LICENSE. If not, write to the -Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. - */ +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ #if HAVE_CONFIG_H -#include "cconfig.h" +#include #endif #include "sel_thread.h" +#if HAVE_UNISTD_H #include +#endif #include -#include + #include #include +#if HAVE_SYS_SOCKET_H #include +#endif +#ifdef WIN32 +#include +#include +#endif +#if HAVE_NETDB_H #include -#include +#endif #include #include #include -#include "pazpar2.h" +#include "session.h" +#include "connection.h" +#include "host.h" + +/* Only use a threaded resolver on Unix that offers getaddrinfo. + gethostbyname is NOT reentrant. + */ +#ifndef WIN32 +#define USE_THREADED_RESOLVER 1 +#endif struct work { char *hostport; /* hostport to be resolved in separate thread */ char *ipport; /* result or NULL if it could not be resolved */ struct host *host; /* host that we're dealing with - mother thread */ + iochan_man_t iochan_man; /* iochan manager */ }; static int log_level = YLOG_LOG; -void perform_getaddrinfo(struct work *w) +static void perform_getaddrinfo(struct work *w) { - int res = 0; - char *port; - struct addrinfo *addrinfo, hints; - char *hostport = xstrdup(w->hostport); - - if ((port = strchr(hostport, ':'))) - *(port++) = '\0'; - else - port = "210"; - + struct addrinfo hints, *res; + char host[512], *cp; + char *port = 0; + int error; + hints.ai_flags = 0; - hints.ai_family = PF_INET; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = 0; - hints.ai_canonname = 0; - hints.ai_next = 0; - // This is not robust code. It assumes that getaddrinfo always - // returns AF_INET address. - if ((res = getaddrinfo(hostport, port, &hints, &addrinfo))) + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + strncpy(host, w->hostport, sizeof(host)-1); + host[sizeof(host)-1] = 0; + if ((cp = strrchr(host, ':'))) + { + *cp = '\0'; + port = cp + 1; + } + error = getaddrinfo(host, port ? port : "210", &hints, &res); + if (error) { - yaz_log(YLOG_WARN, "Failed to resolve %s: %s", - w->hostport, gai_strerror(res)); + yaz_log(YLOG_WARN, "Failed to resolve %s: %s", + w->hostport, gai_strerror(error)); } else { - char ipport[128]; - unsigned char addrbuf[4]; - assert(addrinfo->ai_family == PF_INET); - memcpy(addrbuf, - &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4); - sprintf(ipport, "%u.%u.%u.%u:%s", - addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); - freeaddrinfo(addrinfo); - w->ipport = xstrdup(ipport); - yaz_log(log_level, "Resolved %s -> %s", hostport, ipport); + char n_host[512]; + if (getnameinfo((struct sockaddr *) res->ai_addr, res->ai_addrlen, + n_host, sizeof(n_host)-1, + 0, 0, + NI_NUMERICHOST) == 0) + { + w->ipport = xmalloc(strlen(n_host) + (port ? strlen(port) : 0) + 2); + strcpy(w->ipport, n_host); + if (port) + { + strcat(w->ipport, ":"); + strcat(w->ipport, port); + } + yaz_log(log_level, "Resolved %s -> %s", w->hostport, w->ipport); + } + else + { + yaz_log(YLOG_LOG|YLOG_ERRNO, "getnameinfo failed for %s", + w->hostport); + } + freeaddrinfo(res); } - xfree(hostport); } static void work_handler(void *vp) @@ -99,11 +128,14 @@ static void work_handler(void *vp) if (sec) { yaz_log(log_level, "waiting %d seconds", sec); +#if HAVE_UNISTD_H sleep(sec); +#endif } perform_getaddrinfo(w); } +#if USE_THREADED_RESOLVER void iochan_handler(struct iochan *i, int event) { sel_thread_t p = iochan_getdata(i); @@ -112,17 +144,19 @@ void iochan_handler(struct iochan *i, int event) { struct work *w = sel_thread_result(p); w->host->ipport = w->ipport; - connect_resolver_host(w->host); + connect_resolver_host(w->host, w->iochan_man); xfree(w); } } static sel_thread_t resolver_thread = 0; -static void getaddrinfo_start(void) +static void getaddrinfo_start(iochan_man_t iochan_man) { int fd; - sel_thread_t p = resolver_thread = sel_thread_create(work_handler, &fd); + sel_thread_t p = resolver_thread = + sel_thread_create(work_handler, 0 /* work_destroy */, &fd, + 3 /* no of resolver threads */); if (!p) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "sel_create_create failed"); @@ -130,44 +164,49 @@ static void getaddrinfo_start(void) } else { - IOCHAN chan = iochan_create(fd, iochan_handler, EVENT_INPUT); + IOCHAN chan = iochan_create(fd, iochan_handler, EVENT_INPUT, + "getaddrinfo_socket"); iochan_setdata(chan, p); - pazpar2_add_channel(chan); + iochan_add(iochan_man, chan); } yaz_log(log_level, "resolver start"); resolver_thread = p; } +#endif -int host_getaddrinfo(struct host *host) +int host_getaddrinfo(struct host *host, iochan_man_t iochan_man) { struct work *w = xmalloc(sizeof(*w)); int use_thread = 1; /* =0 to disable threading entirely */ - w->hostport = host->hostport; + w->hostport = host->tproxy ? host->tproxy : host->proxy; w->ipport = 0; w->host = host; + w->iochan_man = iochan_man; +#if USE_THREADED_RESOLVER if (use_thread) { if (resolver_thread == 0) - getaddrinfo_start(); + getaddrinfo_start(iochan_man); assert(resolver_thread); sel_thread_add(resolver_thread, w); + return 0; } - else - { - perform_getaddrinfo(w); - host->ipport = w->ipport; - xfree(w); - if (!host->ipport) - return -1; - } +#endif + perform_getaddrinfo(w); + host->ipport = w->ipport; + xfree(w); + if (!host->ipport) + return -1; return 0; } /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab */ +