diff options
author | Not Zed <NotZed@Ximian.com> | 2001-01-15 15:55:30 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2001-01-15 15:55:30 +0800 |
commit | b64ffc9183d2c94ce6b8fdf10f382904aa8021e8 (patch) | |
tree | 701629078be7b75865fe87c9a348e2d5361004c6 /camel/camel-remote-store.c | |
parent | cff9059380f748309b628041b55abad159aab4d6 (diff) | |
download | gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar.gz gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar.bz2 gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar.lz gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar.xz gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.tar.zst gsoc2013-evolution-b64ffc9183d2c94ce6b8fdf10f382904aa8021e8.zip |
A cancellable connection routine. (remote_send_string): Return cancelled
2001-01-15 Not Zed <NotZed@Ximian.com>
* camel-remote-store.c (socket_connect): A cancellable connection
routine.
(remote_send_string): Return cancelled exception if we were.
(remote_send_stream): "
(remote_recv_line): "
* camel-stream-fs.c (stream_read): First cut at cancellation
stuff. Its looking a bit ugly.
svn path=/trunk/; revision=7496
Diffstat (limited to 'camel/camel-remote-store.c')
-rw-r--r-- | camel/camel-remote-store.c | 134 |
1 files changed, 117 insertions, 17 deletions
diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c index 8d095244e2..9e7a60e378 100644 --- a/camel/camel-remote-store.c +++ b/camel/camel-remote-store.c @@ -25,6 +25,7 @@ #include <config.h> +#include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -205,6 +206,87 @@ timeout_cb (gpointer data) return TRUE; } +/* this is a 'cancellable' connect, cancellable from camel_cancel etc */ +/* returns -1 & errno == EINTR if the connection was cancelled */ +static int socket_connect(struct hostent *h, int port) +{ + struct sockaddr_in sin; + int fd; + int ret; + socklen_t len; + struct timeval tv; + int cancel_fd; + + /* see if we're cancelled yet */ + if (camel_cancel_check(NULL)) { + errno = EINTR; + return -1; + } + + /* setup connect, we do it using a nonblocking socket so we can poll it */ + sin.sin_port = htons(port); + sin.sin_family = h->h_addrtype; + memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); + + fd = socket (h->h_addrtype, SOCK_STREAM, 0); + + cancel_fd = camel_cancel_fd(NULL); + if (cancel_fd == -1) { + ret = connect(fd, (struct sockaddr *)&sin, sizeof (sin)); + if (ret == -1) { + close(fd); + return -1; + } + return fd; + } else { + fd_set rdset, wrset; + long flags; + + fcntl(fd, F_GETFL, &flags); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + ret = connect(fd, (struct sockaddr *)&sin, sizeof (sin)); + if (ret == 0) + return fd; + + if (errno != EINPROGRESS) { + close(fd); + return -1; + } + + FD_ZERO(&rdset); + FD_ZERO(&wrset); + FD_SET(fd, &wrset); + FD_SET(cancel_fd, &rdset); + tv.tv_usec = 0; + tv.tv_sec = 30; + if (select((fd+cancel_fd)/2+1, &rdset, &wrset, 0, &tv) == 0) { + close(fd); + errno = ETIMEDOUT; + return -1; + } + if (cancel_fd != -1 && FD_ISSET(cancel_fd, &rdset)) { + close(fd); + errno = EINTR; + return -1; + } else { + len = sizeof(int); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len) == -1) { + close(fd); + return -1; + } + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } + } + fcntl(fd, F_SETFL, flags); + } + + return fd; +} + static gboolean remote_connect (CamelService *service, CamelException *ex) { @@ -225,6 +307,20 @@ remote_connect (CamelService *service, CamelException *ex) port = service->url->port; else port = store->default_port; + +#if 1 + fd = socket_connect(h, port); + if (fd == -1) { + if (errno == EINTR) + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); + else + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Could not connect to %s (port %d): %s"), + service->url->host ? service->url->host : _("(unknown host)"), + port, strerror (errno)); + return FALSE; + } +#else sin.sin_port = htons (port); memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); @@ -240,6 +336,7 @@ remote_connect (CamelService *service, CamelException *ex) return FALSE; } +#endif /* parent class connect initialization */ if (CAMEL_SERVICE_CLASS (store_class)->connect (service, ex) == FALSE) @@ -322,9 +419,11 @@ remote_send_string (CamelRemoteStore *store, CamelException *ex, char *fmt, va_l #endif if (camel_stream_printf (store->ostream, "%s", cmdbuf) == -1) { + if (errno == EINTR) + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); + else + camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno)); g_free (cmdbuf); - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); return -1; @@ -381,9 +480,11 @@ remote_send_stream (CamelRemoteStore *store, CamelStream *stream, CamelException d(fprintf (stderr, "(sending stream)\n")); ret = camel_stream_write_to_stream (stream, store->ostream); - if (ret < 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); + if (ret == -1) { + if (errno == EINTR) + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); + else + camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); } @@ -446,23 +547,22 @@ remote_recv_line (CamelRemoteStore *store, char **dest, CamelException *ex) if (nread > 0) g_byte_array_append (bytes, buf, nread); } while (nread == sizeof (buf) - 1); - + + if (nread == -1) { + if (errno == EINTR) + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); + else + camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno)); + g_byte_array_free(bytes, TRUE); + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + return -1; + } + g_byte_array_append (bytes, "", 1); ret = bytes->data; nread = bytes->len - 1; g_byte_array_free (bytes, FALSE); - if (nread <= 0) { - g_free (ret); - ret = NULL; - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - nread ? g_strerror (errno) : - _("Server disconnected.")); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - return -1; - } - /* strip off the CRLF sequence */ while (nread > 0 && ret[nread] != '\r') ret[nread--] = '\0'; |