[evolution-data-server/camel-socks-proxy-master] Derive CamelTcpStreamSSL from CamelTcpStreamRaw



commit 3dd79a80868ea25a5ba4f3175ba27d0179618cc7
Author: Federico Mena Quintero <federico novell com>
Date:   Thu Jul 15 16:06:03 2010 -0500

    Derive CamelTcpStreamSSL from CamelTcpStreamRaw
    
    The only overriden vmethod is ::connect(), which starts up SSL on the socket
    after the Raw implementation opens the socket and connects.  By this point,
    we are already past the SOCKS proxy if it exists.
    
    Signed-off-by: Federico Mena Quintero <federico novell com>

 camel/camel-tcp-stream-ssl.c |  748 ++----------------------------------------
 camel/camel-tcp-stream-ssl.h |    7 +-
 2 files changed, 38 insertions(+), 717 deletions(-)
---
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 2a495a6..52847df 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -75,77 +75,13 @@
 	((obj), CAMEL_TYPE_TCP_STREAM_SSL, CamelTcpStreamSSLPrivate))
 
 struct _CamelTcpStreamSSLPrivate {
-	PRFileDesc *sockfd;
-
 	CamelSession *session;
 	gchar *expected_host;
 	gboolean ssl_mode;
 	guint32 flags;
 };
 
-G_DEFINE_TYPE (CamelTcpStreamSSL, camel_tcp_stream_ssl, CAMEL_TYPE_TCP_STREAM)
-
-static void
-set_errno (gint code)
-{
-	/* FIXME: this should handle more. */
-	switch (code) {
-	case PR_INVALID_ARGUMENT_ERROR:
-		errno = EINVAL;
-		break;
-	case PR_PENDING_INTERRUPT_ERROR:
-		errno = EINTR;
-		break;
-	case PR_IO_PENDING_ERROR:
-		errno = EAGAIN;
-		break;
-#ifdef EWOULDBLOCK
-	case PR_WOULD_BLOCK_ERROR:
-		errno = EWOULDBLOCK;
-		break;
-#endif
-#ifdef EINPROGRESS
-	case PR_IN_PROGRESS_ERROR:
-		errno = EINPROGRESS;
-		break;
-#endif
-#ifdef EALREADY
-	case PR_ALREADY_INITIATED_ERROR:
-		errno = EALREADY;
-		break;
-#endif
-#ifdef EHOSTUNREACH
-	case PR_NETWORK_UNREACHABLE_ERROR:
-		errno = EHOSTUNREACH;
-		break;
-#endif
-#ifdef ECONNREFUSED
-	case PR_CONNECT_REFUSED_ERROR:
-		errno = ECONNREFUSED;
-		break;
-#endif
-#ifdef ETIMEDOUT
-	case PR_CONNECT_TIMEOUT_ERROR:
-	case PR_IO_TIMEOUT_ERROR:
-		errno = ETIMEDOUT;
-		break;
-#endif
-#ifdef ENOTCONN
-	case PR_NOT_CONNECTED_ERROR:
-		errno = ENOTCONN;
-		break;
-#endif
-#ifdef ECONNRESET
-	case PR_CONNECT_RESET_ERROR:
-		errno = ECONNRESET;
-		break;
-#endif
-	case PR_IO_ERROR:
-	default:
-		errno = EIO;
-		break;
-	}
-}
+G_DEFINE_TYPE (CamelTcpStreamSSL, camel_tcp_stream_ssl, CAMEL_TYPE_TCP_STREAM_RAW)
 
 static void
 tcp_stream_ssl_dispose (GObject *object)
@@ -170,277 +106,12 @@ tcp_stream_ssl_finalize (GObject *object)
 
 	priv = CAMEL_TCP_STREAM_SSL_GET_PRIVATE (object);
 
-	if (priv->sockfd != NULL) {
-		PR_Shutdown (priv->sockfd, PR_SHUTDOWN_BOTH);
-		PR_Close (priv->sockfd);
-	}
-
 	g_free (priv->expected_host);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (camel_tcp_stream_ssl_parent_class)->finalize (object);
 }
 
-static gssize
-read_from_prfd (PRFileDesc *fd,
-                gchar *buffer,
-                gsize n)
-{
-	PRFileDesc *cancel_fd;
-	gssize nread;
-
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-
-	cancel_fd = camel_operation_cancel_prfd (NULL);
-	if (cancel_fd == NULL) {
-		do {
-			nread = PR_Read (fd, buffer, n);
-			if (nread == -1)
-				set_errno (PR_GetError ());
-		} while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
-					 PR_GetError () == PR_IO_PENDING_ERROR ||
-					 PR_GetError () == PR_WOULD_BLOCK_ERROR));
-	} else {
-		PRSocketOptionData sockopts;
-		PRPollDesc pollfds[2];
-		gboolean nonblock;
-		gint error;
-
-		/* get O_NONBLOCK options */
-		sockopts.option = PR_SockOpt_Nonblocking;
-		PR_GetSocketOption (fd, &sockopts);
-		sockopts.option = PR_SockOpt_Nonblocking;
-		nonblock = sockopts.value.non_blocking;
-		sockopts.value.non_blocking = TRUE;
-		PR_SetSocketOption (fd, &sockopts);
-
-		pollfds[0].fd = fd;
-		pollfds[0].in_flags = PR_POLL_READ;
-		pollfds[1].fd = cancel_fd;
-		pollfds[1].in_flags = PR_POLL_READ;
-
-		do {
-			PRInt32 res;
-
-			pollfds[0].out_flags = 0;
-			pollfds[1].out_flags = 0;
-			nread = -1;
-
-			res = PR_Poll(pollfds, 2, IO_TIMEOUT);
-			if (res == -1)
-				set_errno(PR_GetError());
-			else if (res == 0) {
-#ifdef ETIMEDOUT
-				errno = ETIMEDOUT;
-#else
-				errno = EIO;
-#endif
-				goto failed;
-			} else if (pollfds[1].out_flags == PR_POLL_READ) {
-				errno = EINTR;
-				goto failed;
-			} else {
-				do {
-					nread = PR_Read (fd, buffer, n);
-					if (nread == -1)
-						set_errno (PR_GetError ());
-				} while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
-			}
-		} while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
-					 PR_GetError () == PR_IO_PENDING_ERROR ||
-					 PR_GetError () == PR_WOULD_BLOCK_ERROR));
-
-		/* restore O_NONBLOCK options */
-	failed:
-		error = errno;
-		sockopts.option = PR_SockOpt_Nonblocking;
-		sockopts.value.non_blocking = nonblock;
-		PR_SetSocketOption (fd, &sockopts);
-		errno = error;
-	}
-
-	return nread;
-}
-
-static gssize
-tcp_stream_ssl_read (CamelStream *stream,
-                     gchar *buffer,
-                     gsize n,
-                     GError **error)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	gssize result;
-
-	d (g_print ("SSL stream %p: reading %" G_GSIZE_FORMAT " bytes...\n", ssl, n));
-
-	result = read_from_prfd (ssl->priv->sockfd, buffer, n);
-
-	if (result == -1)
-		g_set_error (
-			error, G_IO_ERROR,
-			g_io_error_from_errno (errno),
-			"%s", g_strerror (errno));
-
-	d (g_print ("SSL stream %p: read %" G_GSSIZE_FORMAT " bytes, errno = %d\n", ssl, result, result == -1 ? errno : 0));
-
-	return result;
-}
-
-static gssize
-write_to_prfd (PRFileDesc *fd, const gchar *buffer, gsize n)
-{
-	gssize w, written = 0;
-	PRFileDesc *cancel_fd;
-
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-
-	cancel_fd = camel_operation_cancel_prfd (NULL);
-	if (cancel_fd == NULL) {
-		do {
-			do {
-				w = PR_Write (fd, buffer + written, n - written);
-				if (w == -1)
-					set_errno (PR_GetError ());
-			} while (w == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
-					     PR_GetError () == PR_IO_PENDING_ERROR ||
-					     PR_GetError () == PR_WOULD_BLOCK_ERROR));
-
-			if (w > 0)
-				written += w;
-		} while (w != -1 && written < n);
-	} else {
-		PRSocketOptionData sockopts;
-		PRPollDesc pollfds[2];
-		gboolean nonblock;
-		gint error;
-
-		/* get O_NONBLOCK options */
-		sockopts.option = PR_SockOpt_Nonblocking;
-		PR_GetSocketOption (fd, &sockopts);
-		sockopts.option = PR_SockOpt_Nonblocking;
-		nonblock = sockopts.value.non_blocking;
-		sockopts.value.non_blocking = TRUE;
-		PR_SetSocketOption (fd, &sockopts);
-
-		pollfds[0].fd = fd;
-		pollfds[0].in_flags = PR_POLL_WRITE;
-		pollfds[1].fd = cancel_fd;
-		pollfds[1].in_flags = PR_POLL_READ;
-
-		do {
-			PRInt32 res;
-
-			pollfds[0].out_flags = 0;
-			pollfds[1].out_flags = 0;
-			w = -1;
-
-			res = PR_Poll (pollfds, 2, IO_TIMEOUT);
-			if (res == -1) {
-				set_errno(PR_GetError());
-				if (PR_GetError () == PR_PENDING_INTERRUPT_ERROR)
-					w = 0;
-			} else if (res == 0) {
-#ifdef ETIMEDOUT
-				errno = ETIMEDOUT;
-#else
-				errno = EIO;
-#endif
-			} else if (pollfds[1].out_flags == PR_POLL_READ) {
-				errno = EINTR;
-			} else {
-				do {
-					w = PR_Write (fd, buffer + written, n - written);
-					if (w == -1)
-						set_errno (PR_GetError ());
-				} while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
-
-				if (w == -1) {
-					if (PR_GetError () == PR_IO_PENDING_ERROR ||
-					    PR_GetError () == PR_WOULD_BLOCK_ERROR)
-						w = 0;
-				} else
-					written += w;
-			}
-		} while (w != -1 && written < n);
-
-		/* restore O_NONBLOCK options */
-		error = errno;
-		sockopts.option = PR_SockOpt_Nonblocking;
-		sockopts.value.non_blocking = nonblock;
-		PR_SetSocketOption (fd, &sockopts);
-		errno = error;
-	}
-
-	if (w == -1)
-		return -1;
-
-	return written;
-}
-
-static gssize
-tcp_stream_ssl_write (CamelStream *stream,
-                      const gchar *buffer,
-                      gsize n,
-                      GError **error)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	gssize result;
-
-	d (g_print ("SSL stream %p: writing %" G_GSIZE_FORMAT " bytes...\n", ssl, n));
-
-	result = write_to_prfd (ssl->priv->sockfd, buffer, n);
-
-	if (result == -1)
-		g_set_error (
-			error, G_IO_ERROR,
-			g_io_error_from_errno (errno),
-			"%s", g_strerror (errno));
-
-	d (g_print ("SSL stream %p: wrote %" G_GSSIZE_FORMAT " bytes, errno = %d\n", ssl, result, result == -1 ? errno : 0));
-
-	return result;
-}
-
-static gint
-tcp_stream_ssl_flush (CamelStream *stream,
-                      GError **error)
-{
-	/*return PR_Sync (((CamelTcpStreamSSL *)stream)->priv->sockfd);*/
-	return 0;
-}
-
-static gint
-tcp_stream_ssl_close (CamelStream *stream,
-                      GError **error)
-{
-	d (g_print ("SSL stream %p: closing\n", stream));
-
-	if (((CamelTcpStreamSSL *)stream)->priv->sockfd == NULL) {
-		errno = EINVAL;
-		g_set_error (
-			error, G_IO_ERROR,
-			g_io_error_from_errno (errno),
-			"%s", g_strerror (errno));
-		return -1;
-	}
-
-	PR_Shutdown (((CamelTcpStreamSSL *)stream)->priv->sockfd, PR_SHUTDOWN_BOTH);
-
-	/* FIXME Need to set the GError if this fails. */
-	if (PR_Close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == PR_FAILURE)
-		return -1;
-
-	((CamelTcpStreamSSL *)stream)->priv->sockfd = NULL;
-
-	return 0;
-}
-
 #if 0
 /* Since this is default implementation, let NSS handle it. */
 static SECStatus
@@ -954,7 +625,9 @@ enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
 {
 	PRFileDesc *ssl_fd;
 
-	ssl_fd = SSL_ImportFD (NULL, fd ? fd : ssl->priv->sockfd);
+	g_assert (fd != NULL);
+
+	ssl_fd = SSL_ImportFD (NULL, fd);
 	if (!ssl_fd)
 		return NULL;
 
@@ -989,8 +662,6 @@ enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
 	 * SSL_AuthCertificateHook callback so we _don't_ need to install one. */
 	SSL_BadCertHook (ssl_fd, ssl_bad_cert, ssl);
 
-	ssl->priv->ssl_mode = TRUE;
-
 	return ssl_fd;
 }
 
@@ -1003,7 +674,7 @@ enable_ssl_or_close_fd (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
 	if (ssl_fd == NULL) {
 		gint errnosave;
 
-		set_errno (PR_GetError ());
+		_set_errno_from_pr_error (PR_GetError ());
 		errnosave = errno;
 		PR_Shutdown (fd, PR_SHUTDOWN_BOTH);
 		PR_Close (fd);
@@ -1015,313 +686,55 @@ enable_ssl_or_close_fd (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
 	return ssl_fd;
 }
 
-static gint
-sockaddr_to_praddr(struct sockaddr *s, gint len, PRNetAddr *addr)
-{
-	/* We assume the ip addresses are the same size - they have to be anyway.
-	   We could probably just use memcpy *shrug* */
-
-	memset(addr, 0, sizeof(*addr));
-
-	if (s->sa_family == AF_INET) {
-		struct sockaddr_in *sin = (struct sockaddr_in *)s;
-
-		if (len < sizeof(*sin))
-			return -1;
-
-		addr->inet.family = PR_AF_INET;
-		addr->inet.port = sin->sin_port;
-		memcpy(&addr->inet.ip, &sin->sin_addr, sizeof(addr->inet.ip));
-
-		return 0;
-	}
-#ifdef ENABLE_IPv6
-	else if (s->sa_family == PR_AF_INET6) {
-		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)s;
-
-		if (len < sizeof(*sin))
-			return -1;
-
-		addr->ipv6.family = PR_AF_INET6;
-		addr->ipv6.port = sin->sin6_port;
-		addr->ipv6.flowinfo = sin->sin6_flowinfo;
-		memcpy(&addr->ipv6.ip, &sin->sin6_addr, sizeof(addr->ipv6.ip));
-		addr->ipv6.scope_id = sin->sin6_scope_id;
-
-		return 0;
-	}
-#endif
-
-	return -1;
-}
-
-static PRFileDesc *
-tcp_socket_ssl_connect (CamelTcpStream *stream, struct addrinfo *host, gboolean possibly_use_ssl)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	PRNetAddr netaddr;
-	PRFileDesc *fd, *cancel_fd;
-
-	if (sockaddr_to_praddr(host->ai_addr, host->ai_addrlen, &netaddr) != 0) {
-		errno = EINVAL;
-		return NULL;
-	}
-
-	fd = PR_OpenTCPSocket(netaddr.raw.family);
-	if (fd == NULL) {
-		set_errno (PR_GetError ());
-		return NULL;
-	}
-
-	if (possibly_use_ssl && ssl->priv->ssl_mode) {
-		fd = enable_ssl_or_close_fd (ssl, fd);
-		if (!fd)
-			return NULL;
-	}
-
-	cancel_fd = camel_operation_cancel_prfd(NULL);
-
-	if (PR_Connect (fd, &netaddr, cancel_fd?0:CONNECT_TIMEOUT) == PR_FAILURE) {
-		gint errnosave;
-
-		set_errno (PR_GetError ());
-		if (PR_GetError () == PR_IN_PROGRESS_ERROR ||
-		    (cancel_fd && (PR_GetError () == PR_CONNECT_TIMEOUT_ERROR ||
-				   PR_GetError () == PR_IO_TIMEOUT_ERROR))) {
-			gboolean connected = FALSE;
-			PRPollDesc poll[2];
-
-			poll[0].fd = fd;
-			poll[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
-			poll[1].fd = cancel_fd;
-			poll[1].in_flags = PR_POLL_READ;
-
-			do {
-				poll[0].out_flags = 0;
-				poll[1].out_flags = 0;
-
-				if (PR_Poll (poll, cancel_fd?2:1, CONNECT_TIMEOUT) == PR_FAILURE) {
-					set_errno (PR_GetError ());
-					goto exception;
-				}
-
-				if (poll[1].out_flags == PR_POLL_READ) {
-					errno = EINTR;
-					goto exception;
-				}
-
-				if (PR_ConnectContinue(fd, poll[0].out_flags) == PR_FAILURE) {
-					set_errno (PR_GetError ());
-					if (PR_GetError () != PR_IN_PROGRESS_ERROR)
-						goto exception;
-				} else {
-					connected = TRUE;
-				}
-			} while (!connected);
-		} else {
-		exception:
-			errnosave = errno;
-			PR_Shutdown (fd, PR_SHUTDOWN_BOTH);
-			PR_Close (fd);
-			errno = errnosave;
-
-			return NULL;
-		}
-
-		errno = 0;
-	}
-
-	return fd;
-}
-
 static gboolean
 rehandshake_ssl (PRFileDesc *fd)
 {
 	if (SSL_ResetHandshake (fd, FALSE) == SECFailure) {
-		set_errno (PR_GetError ());
+		_set_errno_from_pr_error (PR_GetError ());
 		return FALSE;
 	}
 
 	if (SSL_ForceHandshake (fd) == SECFailure) {
-		set_errno (PR_GetError ());
+		_set_errno_from_pr_error (PR_GetError ());
 		return FALSE;
 	}
 
 	return TRUE;
 }
 
-static PRFileDesc *
-connect_to_socks4_proxy (CamelTcpStreamSSL *ssl, const gchar *proxy_host, gint proxy_port, struct addrinfo *connect_addr)
+static gint
+tcp_stream_ssl_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
 {
-	struct addrinfo *ai, hints;
-	gchar serv[16];
-	PRFileDesc *fd;
-	gchar request[9];
-	struct sockaddr_in *sin;
-	gchar reply[8];
-	gint save_errno;
-
-	g_assert (proxy_host != NULL);
-
-	d (g_print ("SSL stream %p: connecting to SOCKS4 proxy %s:%d {\n  resolving proxy host\n", ssl, proxy_host, proxy_port));
-
-	sprintf (serv, "%d", proxy_port);
-
-	memset (&hints, 0, sizeof (hints));
-	hints.ai_socktype = SOCK_STREAM;
-
-	ai = camel_getaddrinfo (proxy_host, serv, &hints, NULL);  /* NULL-GError */
-	if (!ai) {
-#ifdef G_OS_WIN32
-		errno = WSAEHOSTUNREACH;
-#else
-		errno = EHOSTUNREACH; /* FIXME: this is not an accurate error; we should translate the GError to an errno */
-#endif
-		d (g_print ("  camel_getaddrinfo() for the proxy failed\n}\n"));
-		return NULL;
-	}
-
-	d (g_print ("  creating socket and connecting\n"));
-
-	fd = tcp_socket_ssl_connect (CAMEL_TCP_STREAM (ssl), ai, FALSE);
-	save_errno = errno;
-
-	camel_freeaddrinfo (ai);
-
-	if (!fd) {
-		errno = save_errno;
-		d (g_print ("  could not connect: %d\n", errno));
-		goto error;
-	}
-
-	g_assert (connect_addr->ai_addr->sa_family == AF_INET); /* FMQ: check for AF_INET in the caller */
-	sin = (struct sockaddr_in *) connect_addr->ai_addr;
-
-	request[0] = 0x04;				/* SOCKS4 */
-	request[1] = 0x01;				/* CONNECT */
-	memcpy (request + 2, &sin->sin_port, 2);	/* port in network byte order */
-	memcpy (request + 4, &sin->sin_addr.s_addr, 4);	/* address in network byte order */
-	request[8] = 0x00;				/* terminator */
+	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
+	gint retval;
 
-	d (g_print ("  writing SOCKS4 request to connect to actual host\n"));
-	if (write_to_prfd (fd, request, sizeof (request)) != sizeof (request)) {
-		d (g_print ("  failed: %d\n", errno));
-		goto error;
-	}
+	retval = CAMEL_TCP_STREAM_CLASS (parent_class)->connect (stream, host, service, fallback_port, ex);
+	if (retval != 0)
+		return retval;
 
-	d (g_print ("  reading SOCKS4 reply\n"));
-	if (read_from_prfd (fd, reply, sizeof (reply)) != sizeof (reply)) {
-		d (g_print ("  failed: %d\n", errno));
-		goto error;
-	}
+	if (ssl->priv->ssl_mode) {
+		PRFileDesc *fd;
+		PRFileDesc *ssl_fd;
 
-	if (!(reply[0] == 0		/* first byte of reply is 0 */
-	      && reply[1] == 90)) {	/* 90 means "request granted" */
-#ifdef G_OS_WIN32
-		errno = WSAECONNREFUSED;
-#else
-		errno = ECONNREFUSED;
-#endif
-		d (g_print ("  proxy replied with code %d\n", reply[1]));
-		goto error;
-	}
+		d (g_print ("  enabling SSL\n"));
 
-	/* We are now proxied we are ready to send "normal" data through the socket */
+		fd = camel_tcp_stream_get_file_desc (stream);
+		ssl_fd = enable_ssl_or_close_fd (ssl, fd);
+		_camel_tcp_stream_raw_replace_file_desc (CAMEL_TCP_STREAM_RAW (stream), ssl_fd);
 
-	if (ssl->priv->ssl_mode) {
-		d (g_print ("  enabling SSL\n"));
-		fd = enable_ssl_or_close_fd (ssl, fd);
-		if (!fd) {
+		if (!ssl_fd) {
 			d (g_print ("  could not enable SSL\n"));
-			goto error;
 		} else {
 			d (g_print ("  re-handshaking SSL\n"));
-			if (!rehandshake_ssl (fd)) {
+			
+			if (!rehandshake_ssl (ssl_fd)) {
 				d (g_print ("  failed\n"));
-				goto error;
+				return -1;
 			}
 		}
 	}
 
-	d (g_print ("  success\n"));
-
-	goto out;
-
-error:
-	if (fd) {
-		save_errno = errno;
-		PR_Shutdown (fd, PR_SHUTDOWN_BOTH);
-		PR_Close (fd);
-		errno = save_errno;
-		fd = NULL;
-	}
-
-	d (g_print ("  returning errno %d\n", errno));
-
-out:
-
-	d (g_print ("}\n"));
-
-	return fd;
-}
-
-static gint
-tcp_stream_ssl_connect (CamelTcpStream *stream,
-			const char *host, const char *service, gint fallback_port,
-                        GError **error)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	struct addrinfo *addr, *ai;
-	struct addrinfo hints;
-	GError *my_error;
-	gint retval;
-	const gchar *proxy_host;
-	gint proxy_port;
-
-	memset (&hints, 0, sizeof (hints));
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_family = PF_UNSPEC;
-
-	my_error = NULL;
-	addr = camel_getaddrinfo (host, service, &hints, &my_error);
-	if (addr == NULL && fallback_port != 0 && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-		char str_port[16];
-
-		g_clear_error (&my_error);
-		sprintf (str_port, "%d", fallback_port);
-		addr = camel_getaddrinfo (host, str_port, &hints, &my_error);
-	}
-
-	if (addr == NULL) {
-		g_propagate_error (error, my_error);
-		return -1;
-	}
-
-	camel_tcp_stream_peek_socks_proxy (stream, &proxy_host, &proxy_port);
-
-	ai = addr;
-
-	while (ai) {
-		if (proxy_host)
-			ssl->priv->sockfd = connect_to_socks4_proxy (ssl, proxy_host, proxy_port, ai);
-		else
-			ssl->priv->sockfd = socket_connect (stream, ai, TRUE);
-
-		if (ssl->priv->sockfd) {
-			retval = 0;
-			goto out;
-		}
-
-		ai = ai->ai_next;
-	}
-
-	retval = -1;
-
-out:
-
-	camel_freeaddrinfo (addr);
-
-	return retval;
+	return 0;
 }
 
 static gint
@@ -1341,93 +754,10 @@ tcp_stream_ssl_getsockopt (CamelTcpStream *stream,
 	return 0;
 }
 
-static gint
-tcp_stream_ssl_setsockopt (CamelTcpStream *stream,
-                           const CamelSockOptData *data)
-{
-	PRSocketOptionData sodata;
-
-	memset ((gpointer) &sodata, 0, sizeof (sodata));
-	memcpy ((gpointer) &sodata, (gpointer) data, sizeof (CamelSockOptData));
-
-	if (PR_SetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
-		return -1;
-
-	return 0;
-}
-
-static struct sockaddr *
-sockaddr_from_praddr(PRNetAddr *addr, socklen_t *len)
-{
-	/* We assume the ip addresses are the same size - they have to be anyway */
-
-	if (addr->raw.family == PR_AF_INET) {
-		struct sockaddr_in *sin = g_malloc0(sizeof(*sin));
-
-		sin->sin_family = AF_INET;
-		sin->sin_port = addr->inet.port;
-		memcpy(&sin->sin_addr, &addr->inet.ip, sizeof(sin->sin_addr));
-		*len = sizeof(*sin);
-
-		return (struct sockaddr *)sin;
-	}
-#ifdef ENABLE_IPv6
-	else if (addr->raw.family == PR_AF_INET6) {
-		struct sockaddr_in6 *sin = g_malloc0(sizeof(*sin));
-
-		sin->sin6_family = AF_INET6;
-		sin->sin6_port = addr->ipv6.port;
-		sin->sin6_flowinfo = addr->ipv6.flowinfo;
-		memcpy(&sin->sin6_addr, &addr->ipv6.ip, sizeof(sin->sin6_addr));
-		sin->sin6_scope_id = addr->ipv6.scope_id;
-		*len = sizeof(*sin);
-
-		return (struct sockaddr *)sin;
-	}
-#endif
-
-	return NULL;
-}
-
-static struct sockaddr *
-tcp_stream_ssl_get_local_address (CamelTcpStream *stream,
-                                  socklen_t *len)
-{
-	PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
-	PRNetAddr addr;
-
-	if (PR_GetSockName(sockfd, &addr) != PR_SUCCESS)
-		return NULL;
-
-	return sockaddr_from_praddr(&addr, len);
-}
-
-static struct sockaddr *
-tcp_stream_ssl_get_remote_address (CamelTcpStream *stream,
-                                   socklen_t *len)
-{
-	PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
-	PRNetAddr addr;
-
-	if (PR_GetPeerName(sockfd, &addr) != PR_SUCCESS)
-		return NULL;
-
-	return sockaddr_from_praddr(&addr, len);
-}
-
-static PRFileDesc *
-tcp_stream_ssl_get_file_desc (CamelTcpStream *stream)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-
-	return ssl->priv->sockfd;
-}
-
 static void
 camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *class)
 {
 	GObjectClass *object_class;
-	CamelStreamClass *stream_class;
 	CamelTcpStreamClass *tcp_stream_class;
 
 	g_type_class_add_private (class, sizeof (CamelTcpStreamSSLPrivate));
@@ -1436,19 +766,8 @@ camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *class)
 	object_class->dispose = tcp_stream_ssl_dispose;
 	object_class->finalize = tcp_stream_ssl_finalize;
 
-	stream_class = CAMEL_STREAM_CLASS (class);
-	stream_class->read = tcp_stream_ssl_read;
-	stream_class->write = tcp_stream_ssl_write;
-	stream_class->flush = tcp_stream_ssl_flush;
-	stream_class->close = tcp_stream_ssl_close;
-
 	tcp_stream_class = CAMEL_TCP_STREAM_CLASS (class);
 	tcp_stream_class->connect = tcp_stream_ssl_connect;
-	tcp_stream_class->getsockopt = tcp_stream_ssl_getsockopt;
-	tcp_stream_class->setsockopt = tcp_stream_ssl_setsockopt;
-	tcp_stream_class->get_local_address  = tcp_stream_ssl_get_local_address;
-	tcp_stream_class->get_remote_address = tcp_stream_ssl_get_remote_address;
-	tcp_stream_class->get_file_desc = tcp_stream_ssl_get_file_desc;
 }
 
 static void
@@ -1532,19 +851,22 @@ camel_tcp_stream_ssl_new_raw (CamelSession *session, const gchar *expected_host,
 gint
 camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl)
 {
-	PRFileDesc *fd;
+	PRFileDesc *fd, *ssl_fd;
 
 	g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (ssl), -1);
 
-	if (ssl->priv->sockfd && !ssl->priv->ssl_mode) {
-		if (!(fd = enable_ssl (ssl, NULL))) {
-			set_errno (PR_GetError ());
+	fd = camel_tcp_stream_get_file_desc (CAMEL_TCP_STREAM (ssl));
+
+	if (fd && !ssl->priv->ssl_mode) {
+		if (!(ssl_fd = enable_ssl (ssl, fd))) {
+			_set_errno_from_pr_error (PR_GetError ());
 			return -1;
 		}
 
-		ssl->priv->sockfd = fd;
+		_camel_tcp_stream_raw_replace_file_desc (CAMEL_TCP_STREAM_RAW (ssl), ssl_fd);
+		ssl->priv->ssl_mode = TRUE;
 
-		if (!rehandshake_ssl (fd))
+		if (!rehandshake_ssl (ssl_fd))
 			return -1;
 	}
 
diff --git a/camel/camel-tcp-stream-ssl.h b/camel/camel-tcp-stream-ssl.h
index 6e63579..1ea727b 100644
--- a/camel/camel-tcp-stream-ssl.h
+++ b/camel/camel-tcp-stream-ssl.h
@@ -29,8 +29,7 @@
 
 #ifdef HAVE_SSL
 
-#include <camel/camel-tcp-stream.h>
-#include <prio.h>
+#include <camel/camel-tcp-stream-raw.h>
 
 /* Standard GObject macros */
 #define CAMEL_TYPE_TCP_STREAM_SSL \
@@ -64,12 +63,12 @@ typedef struct _CamelTcpStreamSSLClass CamelTcpStreamSSLClass;
 typedef struct _CamelTcpStreamSSLPrivate CamelTcpStreamSSLPrivate;
 
 struct _CamelTcpStreamSSL {
-	CamelTcpStream parent;
+	CamelTcpStreamRaw parent_object;
 	CamelTcpStreamSSLPrivate *priv;
 };
 
 struct _CamelTcpStreamSSLClass {
-	CamelTcpStreamClass parent_class;
+	CamelTcpStreamRawClass parent_class;
 };
 
 GType camel_tcp_stream_ssl_get_type (void);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]