aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2001-03-30 08:31:20 +0800
committerMichael Zucci <zucchi@src.gnome.org>2001-03-30 08:31:20 +0800
commit554de99b229180451331f81adc3f6195bf525878 (patch)
treebf56d161d8c74305a793c95bf483ba28c7caa4f8
parent424506262d215dfe306aea0d0fe86833d08b82a4 (diff)
downloadgsoc2013-evolution-554de99b229180451331f81adc3f6195bf525878.tar.gz
gsoc2013-evolution-554de99b229180451331f81adc3f6195bf525878.tar.zst
gsoc2013-evolution-554de99b229180451331f81adc3f6195bf525878.zip
Not quite finished but checking in for some local frobbing.
2001-03-29 Not Zed <NotZed@Ximian.com> * 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. svn path=/trunk/; revision=9033
-rw-r--r--camel/ChangeLog21
-rw-r--r--camel/camel-remote-store.c1
-rw-r--r--camel/camel-sasl-digest-md5.c2
-rw-r--r--camel/camel-sasl-kerberos4.c1
-rw-r--r--camel/camel-service.c146
-rw-r--r--camel/camel-service.h3
-rw-r--r--camel/camel-vee-folder.c2
-rw-r--r--camel/providers/pop3/camel-pop3-store.c3
-rw-r--r--camel/providers/smtp/camel-smtp-transport.c1
9 files changed, 163 insertions, 17 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 0106940ea4..9ab05a130d 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,23 @@
+2001-03-29 Not Zed <NotZed@Ximian.com>
+
+ * 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 <trow@ximian.com>
* 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 <fejj@ximian.com>
diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c
index 286cd6298f..21bd252c45 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 2200c4945c..fa0d9a8175 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 2f92f1d2a4..1698ffe870 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 20bb00e808..5f6d983435 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -30,10 +30,18 @@
#include <ctype.h>
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef ENABLE_THREADS
+#include <pthread.h>
+#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 ed02f989f4..7850aca4e6 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 ba1cdb5d31..04a06ecbf2 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 17b2fdf8ee..4ebb92dd2b 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 a6572d4bdc..f2c344ebba 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"),