diff options
author | JP Rosevear <jpr@src.gnome.org> | 2005-01-11 08:00:07 +0800 |
---|---|---|
committer | JP Rosevear <jpr@src.gnome.org> | 2005-01-11 08:00:07 +0800 |
commit | fba011bf008443ee5130f1426aa65e11245cd84a (patch) | |
tree | 91793af1cfb21ec9bfea5579abb65ea6f73223b2 /camel/camel-net-utils.c | |
parent | c60c4bf7c4590b850d589d79ac44d057323a429f (diff) | |
download | gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar.gz gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar.bz2 gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar.lz gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar.xz gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.tar.zst gsoc2013-evolution-fba011bf008443ee5130f1426aa65e11245cd84a.zip |
Kill dead files
svn path=/trunk/; revision=28342
Diffstat (limited to 'camel/camel-net-utils.c')
-rw-r--r-- | camel/camel-net-utils.c | 781 |
1 files changed, 0 insertions, 781 deletions
diff --git a/camel/camel-net-utils.c b/camel/camel-net-utils.c deleted file mode 100644 index a4d8159389..0000000000 --- a/camel/camel-net-utils.c +++ /dev/null @@ -1,781 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2004 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/poll.h> -#include <pthread.h> -#include <stdio.h> -#include <errno.h> - -#include <glib.h> - -#include "camel-i18n.h" -#include "camel-operation.h" -#include "camel-exception.h" -#include "camel-net-utils.h" - -#include "libedataserver/e-msgport.h" - -#define d(x) - -/* gethostbyname emulation code for emulating getaddrinfo code ... - -This should probably go away */ - -#ifdef NEED_ADDRINFO - -#if !defined (HAVE_GETHOSTBYNAME_R) || !defined (HAVE_GETHOSTBYADDR_R) -G_LOCK_DEFINE_STATIC (gethost_mutex); -#endif - -#define ALIGN(x) (((x) + (sizeof (char *) - 1)) & ~(sizeof (char *) - 1)) - -#define GETHOST_PROCESS(h, host, buf, buflen, herr) G_STMT_START { \ - int num_aliases = 0, num_addrs = 0; \ - int req_length; \ - char *p; \ - int i; \ - \ - /* check to make sure we have enough room in our buffer */ \ - req_length = 0; \ - if (h->h_aliases) { \ - for (i = 0; h->h_aliases[i]; i++) \ - req_length += strlen (h->h_aliases[i]) + 1; \ - num_aliases = i; \ - } \ - \ - if (h->h_addr_list) { \ - for (i = 0; h->h_addr_list[i]; i++) \ - req_length += h->h_length; \ - num_addrs = i; \ - } \ - \ - req_length += sizeof (char *) * (num_aliases + 1); \ - req_length += sizeof (char *) * (num_addrs + 1); \ - req_length += strlen (h->h_name) + 1; \ - \ - if (buflen < req_length) { \ - *herr = ERANGE; \ - G_UNLOCK (gethost_mutex); \ - return ERANGE; \ - } \ - \ - /* we store the alias/addr pointers in the buffer */ \ - /* their addresses here. */ \ - p = buf; \ - if (num_aliases) { \ - host->h_aliases = (char **) p; \ - p += sizeof (char *) * (num_aliases + 1); \ - } else \ - host->h_aliases = NULL; \ - \ - if (num_addrs) { \ - host->h_addr_list = (char **) p; \ - p += sizeof (char *) * (num_addrs + 1); \ - } else \ - host->h_addr_list = NULL; \ - \ - /* copy the host name into the buffer */ \ - host->h_name = p; \ - strcpy (p, h->h_name); \ - p += strlen (h->h_name) + 1; \ - host->h_addrtype = h->h_addrtype; \ - host->h_length = h->h_length; \ - \ - /* copy the aliases/addresses into the buffer */ \ - /* and assign pointers into the hostent */ \ - *p = 0; \ - if (num_aliases) { \ - for (i = 0; i < num_aliases; i++) { \ - strcpy (p, h->h_aliases[i]); \ - host->h_aliases[i] = p; \ - p += strlen (h->h_aliases[i]); \ - } \ - host->h_aliases[num_aliases] = NULL; \ - } \ - \ - if (num_addrs) { \ - for (i = 0; i < num_addrs; i++) { \ - memcpy (p, h->h_addr_list[i], h->h_length); \ - host->h_addr_list[i] = p; \ - p += h->h_length; \ - } \ - host->h_addr_list[num_addrs] = NULL; \ - } \ -} G_STMT_END - - -#ifdef ENABLE_IPv6 -/* some helpful utils for IPv6 lookups */ -#define IPv6_BUFLEN_MIN (sizeof (char *) * 3) - -static int -ai_to_herr (int error) -{ - switch (error) { - case EAI_NONAME: - case EAI_FAIL: - return HOST_NOT_FOUND; - break; - case EAI_SERVICE: - return NO_DATA; - break; - case EAI_ADDRFAMILY: - return NO_ADDRESS; - break; - case EAI_NODATA: - return NO_DATA; - break; - case EAI_MEMORY: - return ENOMEM; - break; - case EAI_AGAIN: - return TRY_AGAIN; - break; - case EAI_SYSTEM: - return errno; - break; - default: - return NO_RECOVERY; - break; - } -} - -#endif /* ENABLE_IPv6 */ - -static int -camel_gethostbyname_r (const char *name, struct hostent *host, - char *buf, size_t buflen, int *herr) -{ -#ifdef ENABLE_IPv6 - struct addrinfo hints, *res; - int retval, len; - char *addr; - - memset (&hints, 0, sizeof (struct addrinfo)); -#ifdef HAVE_AI_ADDRCONFIG - hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; -#else - hints.ai_flags = AI_CANONNAME; -#endif - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if ((retval = getaddrinfo (name, NULL, &hints, &res)) != 0) { - *herr = ai_to_herr (retval); - return -1; - } - - len = ALIGN (strlen (res->ai_canonname) + 1); - if (buflen < IPv6_BUFLEN_MIN + len + res->ai_addrlen + sizeof (char *)) - return ERANGE; - - /* h_name */ - strcpy (buf, res->ai_canonname); - host->h_name = buf; - buf += len; - - /* h_aliases */ - ((char **) buf)[0] = NULL; - host->h_aliases = (char **) buf; - buf += sizeof (char *); - - /* h_addrtype and h_length */ - host->h_length = res->ai_addrlen; - if (res->ai_family == PF_INET6) { - host->h_addrtype = AF_INET6; - - addr = (char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; - } else { - host->h_addrtype = AF_INET; - - addr = (char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr; - } - - memcpy (buf, addr, host->h_length); - addr = buf; - buf += ALIGN (host->h_length); - - /* h_addr_list */ - ((char **) buf)[0] = addr; - ((char **) buf)[1] = NULL; - host->h_addr_list = (char **) buf; - - freeaddrinfo (res); - - return 0; -#else /* No support for IPv6 addresses */ -#ifdef HAVE_GETHOSTBYNAME_R -#ifdef GETHOSTBYNAME_R_FIVE_ARGS - if (gethostbyname_r (name, host, buf, buflen, herr)) - return 0; - else - return errno; -#else - struct hostent *hp; - int retval; - - retval = gethostbyname_r (name, host, buf, buflen, &hp, herr); - if (hp != NULL) { - *herr = 0; - } else if (retval == 0) { - /* glibc 2.3.2 workaround - it seems that - * gethostbyname_r will sometimes return 0 on fail and - * not set the hostent values (hence the crash in bug - * #56337). Hopefully we can depend on @hp being NULL - * in this error case like we do with - * gethostbyaddr_r(). - */ - retval = -1; - } - - return retval; -#endif -#else /* No support for gethostbyname_r */ - struct hostent *h; - - G_LOCK (gethost_mutex); - - h = gethostbyname (name); - - if (!h) { - *herr = h_errno; - G_UNLOCK (gethost_mutex); - return -1; - } - - GETHOST_PROCESS (h, host, buf, buflen, herr); - - G_UNLOCK (gethost_mutex); - - return 0; -#endif /* HAVE_GETHOSTBYNAME_R */ -#endif /* ENABLE_IPv6 */ -} - -static int -camel_gethostbyaddr_r (const char *addr, int addrlen, int type, struct hostent *host, - char *buf, size_t buflen, int *herr) -{ -#ifdef ENABLE_IPv6 - int retval, len; - - if ((retval = getnameinfo (addr, addrlen, buf, buflen, NULL, 0, NI_NAMEREQD)) != 0) { - *herr = ai_to_herr (retval); - return -1; - } - - len = ALIGN (strlen (buf) + 1); - if (buflen < IPv6_BUFLEN_MIN + len + addrlen + sizeof (char *)) - return ERANGE; - - /* h_name */ - host->h_name = buf; - buf += len; - - /* h_aliases */ - ((char **) buf)[0] = NULL; - host->h_aliases = (char **) buf; - buf += sizeof (char *); - - /* h_addrtype and h_length */ - host->h_length = addrlen; - host->h_addrtype = type; - - memcpy (buf, addr, host->h_length); - addr = buf; - buf += ALIGN (host->h_length); - - /* h_addr_list */ - ((char **) buf)[0] = addr; - ((char **) buf)[1] = NULL; - host->h_addr_list = (char **) buf; - - return 0; -#else /* No support for IPv6 addresses */ -#ifdef HAVE_GETHOSTBYADDR_R -#ifdef GETHOSTBYADDR_R_SEVEN_ARGS - if (gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, herr)) - return 0; - else - return errno; -#else - struct hostent *hp; - int retval; - - retval = gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, &hp, herr); - if (hp != NULL) { - *herr = 0; - retval = 0; - } else if (retval == 0) { - /* glibc 2.3.2 workaround - it seems that - * gethostbyaddr_r will sometimes return 0 on fail and - * fill @host with garbage strings from /etc/hosts - * (failure to parse the file? who knows). Luckily, it - * seems that we can rely on @hp being NULL on - * fail. - */ - retval = -1; - } - - return retval; -#endif -#else /* No support for gethostbyaddr_r */ - struct hostent *h; - - G_LOCK (gethost_mutex); - - h = gethostbyaddr (addr, addrlen, type); - - if (!h) { - *herr = h_errno; - G_UNLOCK (gethost_mutex); - return -1; - } - - GETHOST_PROCESS (h, host, buf, buflen, herr); - - G_UNLOCK (gethost_mutex); - - return 0; -#endif /* HAVE_GETHOSTBYADDR_R */ -#endif /* ENABLE_IPv6 */ -} -#endif /* NEED_ADDRINFO */ - -/* ********************************************************************** */ -struct _addrinfo_msg { - EMsg msg; - unsigned int cancelled:1; - - /* for host lookup */ - const char *name; - const char *service; - int result; - const struct addrinfo *hints; - struct addrinfo **res; - - /* for host lookup emulation */ -#ifdef NEED_ADDRINFO - struct hostent hostbuf; - int hostbuflen; - char *hostbufmem; -#endif - - /* for name lookup */ - const struct sockaddr *addr; - socklen_t addrlen; - char *host; - int hostlen; - char *serv; - int servlen; - int flags; -}; - -static void -cs_freeinfo(struct _addrinfo_msg *msg) -{ - g_free(msg->host); - g_free(msg->serv); -#ifdef NEED_ADDRINFO - g_free(msg->hostbufmem); -#endif - g_free(msg); -} - -/* returns -1 if cancelled */ -static int -cs_waitinfo(void *(worker)(void *), struct _addrinfo_msg *msg, const char *error, CamelException *ex) -{ - EMsgPort *reply_port; - pthread_t id; - int err, cancel_fd, cancel = 0, fd; - - cancel_fd = camel_operation_cancel_fd(NULL); - if (cancel_fd == -1) { - worker(msg); - return 0; - } - - reply_port = msg->msg.reply_port = e_msgport_new(); - fd = e_msgport_fd(msg->msg.reply_port); - if ((err = pthread_create(&id, NULL, worker, msg)) == 0) { - struct pollfd polls[2]; - int status; - - polls[0].fd = fd; - polls[0].events = POLLIN; - polls[1].fd = cancel_fd; - polls[1].events = POLLIN; - - d(printf("waiting for name return/cancellation in main process\n")); - do { - polls[0].revents = 0; - polls[1].revents = 0; - status = poll(polls, 2, -1); - } while (status == -1 && errno == EINTR); - - if (status == -1 || (polls[1].revents & POLLIN)) { - if (status == -1) - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s", error, g_strerror(errno)); - else - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - - /* We cancel so if the thread impl is decent it causes immediate exit. - We detach so we dont need to wait for it to exit if it isn't. - We check the reply port incase we had a reply in the mean time, which we free later */ - d(printf("Cancelling lookup thread and leaving it\n")); - msg->cancelled = 1; - pthread_detach(id); - pthread_cancel(id); - cancel = 1; - } else { - struct _addrinfo_msg *reply = (struct _addrinfo_msg *)e_msgport_get(reply_port); - - g_assert(reply == msg); - d(printf("waiting for child to exit\n")); - pthread_join(id, NULL); - d(printf("child done\n")); - } - } else { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s: %s", error, _("cannot create thread"), g_strerror(err)); - } - e_msgport_destroy(reply_port); - - return cancel; -} - -#ifdef NEED_ADDRINFO -static void * -cs_getaddrinfo(void *data) -{ - struct _addrinfo_msg *msg = data; - int herr; - struct hostent h; - struct addrinfo *res, *last = NULL; - struct sockaddr_in *sin; - in_port_t port = 0; - int i; - - /* This is a pretty simplistic emulation of getaddrinfo */ - - while ((msg->result = camel_gethostbyname_r(msg->name, &h, msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { - pthread_testcancel(); - msg->hostbuflen *= 2; - msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); - } - - /* If we got cancelled, dont reply, just free it */ - if (msg->cancelled) - goto cancel; - - /* FIXME: map error numbers across */ - if (msg->result != 0) - goto reply; - - /* check hints matched */ - if (msg->hints && msg->hints->ai_family && msg->hints->ai_family != h.h_addrtype) { - msg->result = EAI_FAMILY; - goto reply; - } - - /* we only support ipv4 for this interface, even if it could supply ipv6 */ - if (h.h_addrtype != AF_INET) { - msg->result = EAI_FAMILY; - goto reply; - } - - /* check service mapping */ - if (msg->service) { - const char *p = msg->service; - - while (*p) { - if (*p < '0' || *p > '9') - break; - p++; - } - - if (*p) { - const char *socktype = NULL; - struct servent *serv; - - if (msg->hints && msg->hints->ai_socktype) { - if (msg->hints->ai_socktype == SOCK_STREAM) - socktype = "tcp"; - else if (msg->hints->ai_socktype == SOCK_DGRAM) - socktype = "udp"; - } - - serv = getservbyname(msg->service, socktype); - if (serv == NULL) { - msg->result = EAI_NONAME; - goto reply; - } - port = serv->s_port; - } else { - port = htons(strtoul(msg->service, NULL, 10)); - } - } - - for (i=0;h.h_addr_list[i];i++) { - res = g_malloc0(sizeof(*res)); - if (msg->hints) { - res->ai_flags = msg->hints->ai_flags; - if (msg->hints->ai_flags & AI_CANONNAME) - res->ai_canonname = g_strdup(h.h_name); - res->ai_socktype = msg->hints->ai_socktype; - res->ai_protocol = msg->hints->ai_protocol; - } else { - res->ai_flags = 0; - res->ai_socktype = SOCK_STREAM; /* fudge */ - res->ai_protocol = 0; /* fudge */ - } - res->ai_family = AF_INET; - res->ai_addrlen = sizeof(*sin); - res->ai_addr = g_malloc(sizeof(*sin)); - sin = (struct sockaddr_in *)res->ai_addr; - sin->sin_family = AF_INET; - sin->sin_port = port; - memcpy(&sin->sin_addr, h.h_addr_list[i], sizeof(sin->sin_addr)); - - if (last == NULL) { - *msg->res = last = res; - } else { - last->ai_next = res; - last = res; - } - } -reply: - e_msgport_reply((EMsg *)msg); - return NULL; -cancel: - cs_freeinfo(msg); - return NULL; -} -#else -static void * -cs_getaddrinfo(void *data) -{ - struct _addrinfo_msg *info = data; - - info->result = getaddrinfo(info->name, info->service, info->hints, info->res); - - if (info->cancelled) { - g_free(info); - } else { - e_msgport_reply((EMsg *)info); - } - - return NULL; -} -#endif /* NEED_ADDRINFO */ - -struct addrinfo * -camel_getaddrinfo(const char *name, const char *service, const struct addrinfo *hints, CamelException *ex) -{ - struct _addrinfo_msg *msg; - struct addrinfo *res = NULL; -#ifndef ENABLE_IPv6 - struct addrinfo myhints; -#endif - g_return_val_if_fail(name != NULL, NULL); - - if (camel_operation_cancel_check(NULL)) { - camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - return NULL; - } - - camel_operation_start_transient(NULL, _("Resolving: %s"), name); - - /* force ipv4 addresses only */ -#ifndef ENABLE_IPv6 - if (hints == NULL) - memset(&myhints, 0, sizeof(myhints)); - else - memcpy (&myhints, hints, sizeof (myhints)); - - myhints.ai_family = AF_INET; - hints = &myhints; -#endif - - msg = g_malloc0(sizeof(*msg)); - msg->name = name; - msg->service = service; - msg->hints = hints; - msg->res = &res; -#ifdef NEED_ADDRINFO - msg->hostbuflen = 1024; - msg->hostbufmem = g_malloc(msg->hostbuflen); -#endif - if (cs_waitinfo(cs_getaddrinfo, msg, _("Host lookup failed"), ex) == 0) { - if (msg->result != 0) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: %s: %s"), - name, gai_strerror (msg->result)); - - cs_freeinfo(msg); - } else - res = NULL; - - camel_operation_end(NULL); - - return res; -} - -void -camel_freeaddrinfo(struct addrinfo *host) -{ -#ifdef NEED_ADDRINFO - while (host) { - struct addrinfo *next = host->ai_next; - - g_free(host->ai_canonname); - g_free(host->ai_addr); - g_free(host); - host = next; - } -#else - freeaddrinfo(host); -#endif -} - -#ifdef NEED_ADDRINFO -static void * -cs_getnameinfo(void *data) -{ - struct _addrinfo_msg *msg = data; - int herr; - struct hostent h; - struct sockaddr_in *sin = (struct sockaddr_in *)msg->addr; - - /* FIXME: error code */ - if (msg->addr->sa_family != AF_INET) { - msg->result = -1; - return NULL; - } - - /* FIXME: honour getnameinfo flags: do we care, not really */ - - while ((msg->result = camel_gethostbyaddr_r((const char *)&sin->sin_addr, sizeof(sin->sin_addr), AF_INET, &h, - msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { - pthread_testcancel (); - msg->hostbuflen *= 2; - msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); - } - - if (msg->cancelled) - goto cancel; - - if (msg->host) { - g_free(msg->host); - if (msg->result == 0 && h.h_name && h.h_name[0]) { - msg->host = g_strdup(h.h_name); - } else { - unsigned char *in = (unsigned char *)&sin->sin_addr; - - /* sin_addr is always network order which is big-endian */ - msg->host = g_strdup_printf("%u.%u.%u.%u", in[0], in[1], in[2], in[3]); - } - } - - /* we never actually use this anyway */ - if (msg->serv) - sprintf(msg->serv, "%d", sin->sin_port); - - e_msgport_reply((EMsg *)msg); - return NULL; -cancel: - cs_freeinfo(msg); - return NULL; -} -#else -static void * -cs_getnameinfo(void *data) -{ - struct _addrinfo_msg *msg = data; - - /* there doens't appear to be a return code which says host or serv buffers are too short, lengthen them */ - msg->result = getnameinfo(msg->addr, msg->addrlen, msg->host, msg->hostlen, msg->serv, msg->servlen, msg->flags); - - if (msg->cancelled) - cs_freeinfo(msg); - else - e_msgport_reply((EMsg *)msg); - - return NULL; -} -#endif - -int -camel_getnameinfo(const struct sockaddr *sa, socklen_t salen, char **host, char **serv, int flags, CamelException *ex) -{ - struct _addrinfo_msg *msg; - int result; - - if (camel_operation_cancel_check(NULL)) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - return -1; - } - - camel_operation_start_transient(NULL, _("Resolving address")); - - msg = g_malloc0(sizeof(*msg)); - msg->addr = sa; - msg->addrlen = salen; - if (host) { - msg->hostlen = NI_MAXHOST; - msg->host = g_malloc(msg->hostlen); - msg->host[0] = 0; - } - if (serv) { - msg->servlen = NI_MAXSERV; - msg->serv = g_malloc(msg->servlen); - msg->serv[0] = 0; - } - msg->flags = flags; -#ifdef NEED_ADDRINFO - msg->hostbuflen = 1024; - msg->hostbufmem = g_malloc(msg->hostbuflen); -#endif - cs_waitinfo(cs_getnameinfo, msg, _("Name lookup failed"), ex); - - if ((result = msg->result) != 0) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Name lookup failed: %s"), - gai_strerror (result)); - - if (host) - *host = g_strdup(msg->host); - if (serv) - *serv = g_strdup(msg->serv); - - g_free(msg->host); - g_free(msg->serv); - g_free(msg); - - camel_operation_end(NULL); - - return result; -} |