aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog20
-rw-r--r--camel/Makefile.am4
-rw-r--r--camel/camel-remote-store.c141
-rw-r--r--camel/camel-tcp-stream-raw.c109
-rw-r--r--camel/camel-tcp-stream-ssl.c4
-rw-r--r--camel/camel-tcp-stream.h9
-rw-r--r--camel/camel-types.h2
7 files changed, 163 insertions, 126 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 9fea64d53c..dcf2d2117e 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,25 @@
2001-03-13 Jeffrey Stedfast <fejj@ximian.com>
+ * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_get_type):
+ Oops. Make this a subclass of CamelTcpStream, not CamelStream.
+
+ * camel-types.h: Add the defs for CamelTcpStream and
+ CamelTcpStreamRaw
+
+ * Makefile.am: Add camel-tcp-stream and camel-tcp-stream-raw to
+ the build.
+
+ * camel-remote-store.c (remote_connect): Update to use
+ CamelTcpStreams.
+
+ * camel-tcp-stream-raw.c (stream_connect): Made cancellable by
+ copying the currently used code in camel-remote-store.c.
+ (stream_setsockopt): Oops, flags = fcntl (..., GET_FL);
+ (camel_tcp_stream_raw_get_type): Oops. Make this a subclass of
+ CamelTcpStream, not CamelStream.
+
+2001-03-13 Jeffrey Stedfast <fejj@ximian.com>
+
* camel.c (camel_init): Since all of the Mozilla libs (including
NSPR and NSS) correctly handle reinitializations, we might as well
init both NSPR and NSS in camel_init so we can be sure of that
diff --git a/camel/Makefile.am b/camel/Makefile.am
index da1bc24c43..9b3390d53d 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -68,6 +68,8 @@ libcamel_la_SOURCES = \
camel-stream-mem.c \
camel-stream-null.c \
camel-stream.c \
+ camel-tcp-stream-raw.c \
+ camel-tcp-stream.c \
camel-transport.c \
camel-uid-cache.c \
camel-url.c \
@@ -132,6 +134,8 @@ libcamelinclude_HEADERS = \
camel-stream-mem.h \
camel-stream-null.h \
camel-stream.h \
+ camel-tcp-stream-raw.h \
+ camel-tcp-stream.h \
camel-transport.h \
camel-types.h \
camel-uid-cache.h \
diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c
index f756eb5ac8..681aca0113 100644
--- a/camel/camel-remote-store.c
+++ b/camel/camel-remote-store.c
@@ -42,7 +42,12 @@
#include "camel-session.h"
#include "camel-stream.h"
#include "camel-stream-buffer.h"
-#include "camel-stream-fs.h"
+#include "camel-tcp-stream.h"
+#include "camel-tcp-stream-raw.h"
+#if HAVE_NSS
+#include "camel-tcp-stream-ssl.h"
+#endif
+
#include "camel-url.h"
#include "string-utils.h"
@@ -194,147 +199,51 @@ timeout_cb (gpointer data)
return TRUE;
}
-/* this is a 'cancellable' connect, cancellable from camel_operation_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_operation_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_operation_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;
- int flags, fdmax;
-
- flags = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-
- ret = connect(fd, (struct sockaddr *)&sin, sizeof (sin));
- if (ret == 0) {
- fcntl(fd, F_SETFL, flags);
- return fd;
- }
-
- if (errno != EINPROGRESS) {
- close(fd);
- return -1;
- }
-
- FD_ZERO(&rdset);
- FD_ZERO(&wrset);
- FD_SET(fd, &wrset);
- FD_SET(cancel_fd, &rdset);
- fdmax = MAX(fd, cancel_fd)+1;
- tv.tv_usec = 0;
- tv.tv_sec = 60*4;
- if (select(fdmax, &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)
{
CamelRemoteStore *store = CAMEL_REMOTE_STORE (service);
+ CamelStream *tcp_stream;
struct hostent *h;
- struct sockaddr_in sin;
- gint fd;
- gint port;
+ gint ret, port;
h = camel_service_gethost (service, ex);
if (!h)
return FALSE;
- /* connect to the server */
- sin.sin_family = h->h_addrtype;
-
if (service->url->port)
port = service->url->port;
else
port = store->default_port;
-
-#if 1
- fd = socket_connect(h, port);
- if (fd == -1) {
+
+#ifdef HAVE_NSS
+ if (store->use_ssl)
+ tcp_stream = camel_tcp_stream_ssl_new ();
+ else
+ tcp_stream = camel_tcp_stream_raw_new ();
+#else
+ tcp_stream = camel_tcp_stream_raw_new ();
+#endif /* HAVE_NSS */
+
+ ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port);
+ if (ret == -1) {
if (errno == EINTR)
- camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled"));
+ 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));
-
- fd = socket (h->h_addrtype, SOCK_STREAM, 0);
- if (fd == -1 || connect (fd, (struct sockaddr *)&sin, sizeof (sin)) == -1) {
- 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, g_strerror (errno));
- if (fd > -1)
- close (fd);
-
+ port, g_strerror (errno));
return FALSE;
}
-#endif
/* parent class connect initialization */
if (CAMEL_SERVICE_CLASS (store_class)->connect (service, ex) == FALSE)
return FALSE;
- store->ostream = camel_stream_fs_new_with_fd (fd);
- store->istream = camel_stream_buffer_new (store->ostream, CAMEL_STREAM_BUFFER_READ);
+ store->ostream = tcp_stream;
+ store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
/* Okay, good enough for us */
CAMEL_SERVICE (store)->connected = TRUE;
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index 6467eed5da..bc9223a267 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -23,9 +23,11 @@
#include <config.h>
#include "camel-tcp-stream-raw.h"
-#include <unistd.h>
+#include "camel-operation.h"
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
@@ -52,7 +54,7 @@ camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *camel_tcp_stream_raw_cl
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_tcp_stream_raw_class);
- parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
+ parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
/* virtual method overload */
camel_stream_class->read = stream_read;
@@ -89,7 +91,7 @@ camel_tcp_stream_raw_get_type (void)
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register (camel_stream_get_type (),
+ type = camel_type_register (camel_tcp_stream_get_type (),
"CamelTcpStreamRaw",
sizeof (CamelTcpStreamRaw),
sizeof (CamelTcpStreamRawClass),
@@ -165,16 +167,114 @@ stream_close (CamelStream *stream)
return 0;
}
+/* this is a 'cancellable' connect, cancellable from camel_operation_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_operation_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_operation_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;
+ int flags, fdmax;
+
+ flags = fcntl (fd, F_GETFL);
+ fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+
+ ret = connect (fd, (struct sockaddr *)&sin, sizeof (sin));
+ if (ret == 0) {
+ fcntl (fd, F_SETFL, flags);
+ return fd;
+ }
+
+ if (errno != EINPROGRESS) {
+ close (fd);
+ return -1;
+ }
+
+ FD_ZERO (&rdset);
+ FD_ZERO (&wrset);
+ FD_SET (fd, &wrset);
+ FD_SET (cancel_fd, &rdset);
+ fdmax = MAX (fd, cancel_fd) + 1;
+ tv.tv_usec = 0;
+ tv.tv_sec = 60 * 4;
+
+ if (select (fdmax, &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;
+}
+#define DIVINE_INTERVENTION
static int
stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
+#ifndef DIVINE_INTERVENTION
struct sockaddr_in sin;
+#endif
int fd;
g_return_val_if_fail (host != NULL, -1);
+#ifdef DIVINE_INTERVENTION
+ fd = socket_connect (host, port);
+ if (fd == -1)
+ return -1;
+#else
sin.sin_family = host->h_addrtype;
sin.sin_port = htons (port);
@@ -188,6 +288,7 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
return -1;
}
+#endif
raw->sockfd = fd;
@@ -272,7 +373,7 @@ stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
int flags, set;
- fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL);
+ flags = fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL);
if (flags == -1)
return -1;
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 14e26bc706..15b907845a 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -62,7 +62,7 @@ camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_cl
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class);
- parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
+ parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
/* virtual method overload */
camel_stream_class->read = stream_read;
@@ -104,7 +104,7 @@ camel_tcp_stream_ssl_get_type (void)
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register (camel_stream_get_type (),
+ type = camel_type_register (camel_tcp_stream_get_type (),
"CamelTcpStreamSSL",
sizeof (CamelTcpStreamSSL),
sizeof (CamelTcpStreamSSLClass),
diff --git a/camel/camel-tcp-stream.h b/camel/camel-tcp-stream.h
index 56afa7a1fd..79d3f90f08 100644
--- a/camel/camel-tcp-stream.h
+++ b/camel/camel-tcp-stream.h
@@ -35,6 +35,7 @@ extern "C" {
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#include <netdb.h>
#include <unistd.h>
#define CAMEL_TCP_STREAM_TYPE (camel_tcp_stream_get_type ())
@@ -99,16 +100,16 @@ typedef struct {
int (*connect) (CamelTcpStream *stream, struct hostent *host, int port);
int (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data);
int (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data);
-
+
} CamelTcpStreamClass;
/* Standard Camel function */
CamelType camel_tcp_stream_get_type (void);
/* public methods */
-int camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
-int camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
-int camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
+int camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
+int camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
+int camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
#ifdef __cplusplus
}
diff --git a/camel/camel-types.h b/camel/camel-types.h
index 8cf64d17ff..eed0ff99a6 100644
--- a/camel/camel-types.h
+++ b/camel/camel-types.h
@@ -64,6 +64,8 @@ typedef struct _CamelStreamDataWrapper CamelStreamDataWrapper;
typedef struct _CamelStreamFilter CamelStreamFilter;
typedef struct _CamelStreamFs CamelStreamFs;
typedef struct _CamelStreamMem CamelStreamMem;
+typedef struct _CamelTcpStream CamelTcpStream;
+typedef struct _CamelTcpStreamRaw CamelTcpStreamRaw;
typedef struct _CamelTransport CamelTransport;
#ifdef __cplusplus