From: Not Zed Date: Fri, 30 Mar 2001 00:31:20 +0000 (+0000) Subject: Not quite finished but checking in for some local frobbing. X-Git-Tag: upstream/3.7.4~11000 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=53284f960ec9030309791f5a0e614200285bee3e;p=platform%2Fupstream%2Fevolution-data-server.git Not quite finished but checking in for some local frobbing. 2001-03-29 Not Zed * providers/smtp/camel-smtp-transport.c (smtp_connect): Free host name info when done ... blah blah. * camel-sasl-kerberos4.c (krb4_challenge): Free host name info after we're done with it. * camel-sasl-digest-md5.c (digest_md5_challenge): Free host name info after we're done with it. * camel-remote-store.c (remote_connect): Free the host name info from get_host after we're finished with it. * camel-service.c (camel_get_host_byname): New function to lookup a name, and still be cancellable. (camel_free_host): And a function to free the structure returned. (camel_service_gethost): Call get_host_byname for this. --- diff --git a/camel/ChangeLog b/camel/ChangeLog index 0106940..9ab05a1 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,23 @@ +2001-03-29 Not Zed + + * providers/smtp/camel-smtp-transport.c (smtp_connect): Free host + name info when done ... blah blah. + + * camel-sasl-kerberos4.c (krb4_challenge): Free host name info + after we're done with it. + + * camel-sasl-digest-md5.c (digest_md5_challenge): Free host name + info after we're done with it. + + * camel-remote-store.c (remote_connect): Free the host name info + from get_host after we're finished with it. + + * camel-service.c (camel_get_host_byname): New function to + lookup a name, and still be cancellable. + (camel_free_host): And a function to free the structure + returned. + (camel_service_gethost): Call get_host_byname for this. + 2001-03-29 Jon Trowbridge * camel-filter-driver.c (camel_filter_driver_filter_message): Save @@ -182,6 +202,7 @@ (camel_vee_folder_hash_folder): Made public (renamed from hash_folder), simply for subclasses (probably not needed). (vee_expunge): Oops, call the class sync, not superclass sync. + (vee_sync): Remove some accidental debug. 2001-03-27 Jeffrey Stedfast diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c index 286cd62..21bd252 100644 --- a/camel/camel-remote-store.c +++ b/camel/camel-remote-store.c @@ -236,6 +236,7 @@ remote_connect (CamelService *service, CamelException *ex) #endif /* HAVE_NSS */ ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); + camel_free_host(h); if (ret == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, diff --git a/camel/camel-sasl-digest-md5.c b/camel/camel-sasl-digest-md5.c index 2200c49..fa0d9a8 100644 --- a/camel/camel-sasl-digest-md5.c +++ b/camel/camel-sasl-digest-md5.c @@ -823,7 +823,7 @@ digest_md5_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) priv->response = generate_response (priv->challenge, h, sasl->service_name, sasl->service->url->user, sasl->service->url->passwd); - + camel_free_host(h); ret = digest_response (priv->response); break; diff --git a/camel/camel-sasl-kerberos4.c b/camel/camel-sasl-kerberos4.c index 2f92f1d..1698ffe 100644 --- a/camel/camel-sasl-kerberos4.c +++ b/camel/camel-sasl-kerberos4.c @@ -146,6 +146,7 @@ krb4_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) inst = g_strndup (h->h_name, strcspn (h->h_name, ".")); g_strdown (inst); realm = g_strdup (krb_realmofhost (h->h_name)); + camel_free_host(h); status = krb_mk_req (&authenticator, sasl->service_name, inst, realm, priv->nonce_h); if (status == KSUCCESS) { status = krb_get_cred (sasl->service_name, inst, realm, &credentials); diff --git a/camel/camel-service.c b/camel/camel-service.c index 20bb00e..5f6d983 100644 --- a/camel/camel-service.c +++ b/camel/camel-service.c @@ -30,10 +30,18 @@ #include #include +#include +#include + +#ifdef ENABLE_THREADS +#include +#include "e-util/e-msgport.h" +#endif #include "camel-service.h" #include "camel-session.h" #include "camel-exception.h" +#include "camel-operation.h" #include "camel-private.h" static CamelObjectClass *parent_class = NULL; @@ -469,29 +477,139 @@ camel_service_query_auth_types (CamelService *service, CamelException *ex) struct hostent * camel_service_gethost (CamelService *service, CamelException *ex) { - struct hostent *h; char *hostname; - -#warning "This needs to use gethostbyname_r()" + struct hostent *h; if (service->url->host) hostname = service->url->host; else hostname = "localhost"; - h = gethostbyname (hostname); - if (!h) { - extern int h_errno; - if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("No such host %s."), hostname); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Temporarily unable to look " - "up hostname %s."), hostname); + return camel_get_host_byname(hostname, ex); +} + +#ifdef offsetof +#define STRUCT_OFFSET(type, field) ((gint) offsetof (type, field)) +#else +#define STRUCT_OFFSET(type, field) ((gint) ((gchar*) &((type *) 0)->field)) +#endif + +struct _lookup_msg { +#ifdef ENABLE_THREADS + EMsg msg; +#endif + const char *name; + int result; + int herr; + struct hostent hostbuf; + struct hostent *hp; + int hostbuflen; + char *hostbufmem; +}; + +static void * +get_host(void *data) +{ + struct _lookup_msg *info = data; + + while ((info->result = gethostbyname_r(info->name, &info->hostbuf, info->hostbufmem, info->hostbuflen, &info->hp, &info->herr)) == ERANGE) { + printf("gethostbyname fialed?\n"); +#ifdef ENABLE_THREADS + pthread_testcancel(); +#endif + info->hostbuflen *= 2; + info->hostbufmem = g_realloc(info->hostbufmem, info->hostbuflen); + } + + printf("gethostbyname ok?\n"); + +#ifdef ENABLE_THREADS + e_msgport_reply((EMsg *)info); +#endif + return NULL; +} + +struct hostent *camel_get_host_byname(const char *name, CamelException *ex) +{ +#ifdef ENABLE_THREADS + int fdmax, fd, cancel_fd; +#endif + struct _lookup_msg *msg; + + g_return_val_if_fail(name != NULL, NULL); + + if (camel_operation_cancel_check(NULL)) { + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + return NULL; + } + + msg = g_malloc0(sizeof(*msg)); + msg->hostbuflen = 1024; + msg->hostbufmem = g_malloc(msg->hostbuflen); + msg->name = name; + +#ifdef ENABLE_THREADS + cancel_fd = camel_operation_cancel_fd(NULL); + if (cancel_fd == -1) { +#endif + get_host(msg); +#ifdef ENABLE_THREADS + } else { + EMsgPort *reply_port; + pthread_t id; + fd_set rdset; + + reply_port = msg->msg.reply_port = e_msgport_new(); + fd = e_msgport_fd(msg->msg.reply_port); + if (pthread_create(&id, NULL, get_host, msg) == 0) { + FD_ZERO(&rdset); + FD_SET(cancel_fd, &rdset); + FD_SET(fd, &rdset); + fdmax = MAX(fd, cancel_fd) + 1; + printf("waiting for name return/cancellation in main process\n"); + if (select(fdmax, &rdset, NULL, 0, NULL) == -1) { + camel_exception_setv(ex, 1, _("Failure in name lookup: %s"), strerror(errno)); + printf("Cancelling lookup thread\n"); + pthread_cancel(id); + } else if (FD_ISSET(cancel_fd, &rdset)) { + printf("Cancelling lookup thread\n"); + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + pthread_cancel(id); + } else { + struct _lookup_msg *reply = (struct _lookup_msg *)e_msgport_get(reply_port); + + g_assert(reply == msg); + } + printf("waiting for child to exit\n"); + pthread_join(id, NULL); } + e_msgport_destroy(reply_port); + } +#endif + + if (msg->hp == NULL) { + if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) + camel_exception_setv(ex, 1, _("Host lookup failed: %s: host not found"), name); + else + camel_exception_setv(ex, 1, _("Host lookup failed: %s: unknown reason"), name); + g_free(msg->hostbufmem); + g_free(msg); return NULL; + } else { + return &msg->hostbuf; } +} + +void camel_free_host(struct hostent *h) +{ + struct _lookup_msg *msg; + + g_return_if_fail(h != NULL); + + /* yeah this looks ugly but it is safe. we passed out a reference to inside our structure, this maps it + to the base structure, so we can free everything right without having to keep track of it separately */ + msg = (struct _lookup_msg *)(((char *)h) - STRUCT_OFFSET(struct _lookup_msg, hostbuf)); - return h; + g_free(msg->hostbufmem); + g_free(msg); } diff --git a/camel/camel-service.h b/camel/camel-service.h index ed02f98..7850aca 100644 --- a/camel/camel-service.h +++ b/camel/camel-service.h @@ -112,6 +112,9 @@ GList * camel_service_query_auth_types (CamelService *service, struct hostent * camel_service_gethost (CamelService *service, CamelException *ex); +/* cancellable dns lookup */ +struct hostent * camel_get_host_byname (const char *name, CamelException *ex); +void camel_free_host (struct hostent *h); /* Standard Camel function */ CamelType camel_service_get_type (void); diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index ba1cdb5..04a06ec 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -411,8 +411,6 @@ vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GList *node; - printf("vee-sync\n"); - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); node = p->folders; diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c index 17b2fdf..4ebb92d 100644 --- a/camel/providers/pop3/camel-pop3-store.c +++ b/camel/providers/pop3/camel-pop3-store.c @@ -169,9 +169,12 @@ connect_to_server (CamelService *service, CamelException *ex) /* Need to copy hostname, because krb_realmofhost will * call gethostbyname as well, and gethostbyname uses * static storage. + * This isn't really necessary since gethost() returns a copy anyway, + * but for simplicity leave the old code here - NZ */ h = camel_service_gethost (service, ex); hostname = g_strdup (h->h_name); + camel_free_host(h); fd = CAMEL_STREAM_FS (CAMEL_REMOTE_STORE (service)->ostream)->fd; diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c index a6572d4b..f2c344e 100644 --- a/camel/providers/smtp/camel-smtp-transport.c +++ b/camel/providers/smtp/camel-smtp-transport.c @@ -255,6 +255,7 @@ smtp_connect (CamelService *service, CamelException *ex) #endif /* HAVE_NSS */ ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); + camel_free_host(h); if (ret == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Could not connect to %s (port %d): %s"),