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



commit 442e360db7384763455d24c1ef0c0df78235115a
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 |  731 ++----------------------------------------
 camel/camel-tcp-stream-ssl.h |    7 +-
 2 files changed, 38 insertions(+), 700 deletions(-)
---
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index cec0dac..1e5b4c8 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -67,28 +67,16 @@
 #define IO_TIMEOUT (PR_TicksPerSecond() * 4 * 60)
 #define CONNECT_TIMEOUT (PR_TicksPerSecond () * 4 * 60)
 
-static CamelTcpStreamClass *parent_class = NULL;
+static CamelTcpStreamRawClass *parent_class = NULL;
 
 /* Returns the class for a CamelTcpStreamSSL */
 #define CTSS_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so))
 
-static gssize stream_read (CamelStream *stream, gchar *buffer, gsize n);
-static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n);
-static gint stream_flush  (CamelStream *stream);
-static gint stream_close  (CamelStream *stream);
-
 static PRFileDesc *enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd);
 
 static gint stream_connect    (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
-static gint stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
-static gint stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
-static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
-static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
-static PRFileDesc *stream_get_file_desc (CamelTcpStream *stream);
 
 struct _CamelTcpStreamSSLPrivate {
-	PRFileDesc *sockfd;
-
 	struct _CamelSession *session;
 	gchar *expected_host;
 	gboolean ssl_mode;
@@ -100,23 +88,12 @@ camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_cl
 {
 	CamelTcpStreamClass *camel_tcp_stream_class =
 		CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class);
-	CamelStreamClass *camel_stream_class =
-		CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class);
 
-	parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
+	parent_class = CAMEL_TCP_STREAM_RAW_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_raw_get_type ()));
 
 	/* virtual method overload */
-	camel_stream_class->read = stream_read;
-	camel_stream_class->write = stream_write;
-	camel_stream_class->flush = stream_flush;
-	camel_stream_class->close = stream_close;
 
 	camel_tcp_stream_class->connect = stream_connect;
-	camel_tcp_stream_class->getsockopt = stream_getsockopt;
-	camel_tcp_stream_class->setsockopt = stream_setsockopt;
-	camel_tcp_stream_class->get_local_address  = stream_get_local_address;
-	camel_tcp_stream_class->get_remote_address = stream_get_remote_address;
-	camel_tcp_stream_class->get_file_desc = stream_get_file_desc;
 }
 
 static void
@@ -132,11 +109,6 @@ camel_tcp_stream_ssl_finalize (CamelObject *object)
 {
 	CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
 
-	if (stream->priv->sockfd != NULL) {
-		PR_Shutdown (stream->priv->sockfd, PR_SHUTDOWN_BOTH);
-		PR_Close (stream->priv->sockfd);
-	}
-
 	if (stream->priv->session)
 		camel_object_unref(stream->priv->session);
 
@@ -151,7 +123,7 @@ camel_tcp_stream_ssl_get_type (void)
 	static CamelType type = CAMEL_INVALID_TYPE;
 
 	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_tcp_stream_get_type (),
+		type = camel_type_register (camel_tcp_stream_raw_get_type (),
 					    "CamelTcpStreamSSL",
 					    sizeof (CamelTcpStreamSSL),
 					    sizeof (CamelTcpStreamSSLClass),
@@ -230,78 +202,16 @@ camel_tcp_stream_ssl_new_raw (CamelSession *session, const gchar *expected_host,
 	return CAMEL_STREAM (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;
-	}
-}
-
 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;
 	}
 
@@ -319,19 +229,22 @@ rehandshake_ssl (PRFileDesc *fd)
 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;
 	}
 
@@ -340,238 +253,6 @@ camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl)
 	return 0;
 }
 
-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
-stream_read (CamelStream *stream, gchar *buffer, gsize n)
-{
-	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);
-
-	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
-stream_write (CamelStream *stream, const gchar *buffer, gsize n)
-{
-	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);
-
-	d (g_print ("SSL stream %p: wrote %" G_GSSIZE_FORMAT " bytes, errno = %d\n", ssl, result, result == -1 ? errno : 0));
-
-	return result;
-}
-
-static gint
-stream_flush (CamelStream *stream)
-{
-	/*return PR_Sync (((CamelTcpStreamSSL *)stream)->priv->sockfd);*/
-	return 0;
-}
-
-static gint
-stream_close (CamelStream *stream)
-{
-	d (g_print ("SSL stream %p: closing\n", stream));
-
-	if (((CamelTcpStreamSSL *)stream)->priv->sockfd == NULL) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	PR_Shutdown (((CamelTcpStreamSSL *)stream)->priv->sockfd, PR_SHUTDOWN_BOTH);
-	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
@@ -1082,7 +763,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;
 
@@ -1117,8 +800,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;
 }
 
@@ -1131,7 +812,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);
@@ -1144,381 +825,39 @@ enable_ssl_or_close_fd (CamelTcpStreamSSL *ssl, PRFileDesc *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 *
-socket_connect(CamelTcpStream *stream, struct addrinfo *host, gboolean possibly_use_ssl)
+stream_connect(CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
 {
 	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 PRFileDesc *
-connect_to_socks4_proxy (CamelTcpStreamSSL *ssl, const gchar *proxy_host, gint proxy_port, struct addrinfo *connect_addr)
-{
-	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-CamelException */
-	if (!ai) {
-		errno = EHOSTUNREACH; /* FIXME: this is not an accurate error; we should translate the CamelException to an errno */
-		d (g_print ("  camel_getaddrinfo() for the proxy failed\n}\n"));
-		return NULL;
-	}
-
-	d (g_print ("  creating socket and connecting\n"));
-
-	fd = socket_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 */
+	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" */
-		errno = ECONNREFUSED;
-		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;
+			return -1;
 		} 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
-stream_connect(CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	struct addrinfo *addr, *ai;
-	struct addrinfo hints;
-	CamelException my_ex;
-	gint retval;
-	const gchar *proxy_host;
-	gint proxy_port;
-
-	memset (&hints, 0, sizeof (hints));
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_family = PF_UNSPEC;
-
-	camel_exception_init (&my_ex);
-	addr = camel_getaddrinfo (host, service, &hints, &my_ex);
-	if (addr == NULL && fallback_port != 0 && camel_exception_get_id (&my_ex) != CAMEL_EXCEPTION_USER_CANCEL) {
-		char str_port[16];
-
-		camel_exception_clear (&my_ex);
-		sprintf (str_port, "%d", fallback_port);
-		addr = camel_getaddrinfo (host, str_port, &hints, &my_ex);
-	}
-
-	if (addr == NULL) {
-		camel_exception_xfer (ex, &my_ex);
-		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;
-}
-
-static gint
-stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
-{
-	PRSocketOptionData sodata;
-
-	memset ((gpointer) &sodata, 0, sizeof (sodata));
-	memcpy ((gpointer) &sodata, (gpointer) data, sizeof (CamelSockOptData));
-
-	if (PR_GetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
-		return -1;
-
-	memcpy ((gpointer) data, (gpointer) &sodata, sizeof (CamelSockOptData));
-
-	return 0;
-}
-
-static gint
-stream_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 *
-stream_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 *
-stream_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 *
-stream_get_file_desc (CamelTcpStream *stream)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-
-	return ssl->priv->sockfd;
-}
-
 #endif /* HAVE_NSS */
diff --git a/camel/camel-tcp-stream-ssl.h b/camel/camel-tcp-stream-ssl.h
index 352e0f4..1f81ede 100644
--- a/camel/camel-tcp-stream-ssl.h
+++ b/camel/camel-tcp-stream-ssl.h
@@ -23,8 +23,7 @@
 #ifndef CAMEL_TCP_STREAM_SSL_H
 #define CAMEL_TCP_STREAM_SSL_H
 
-#include <camel/camel-tcp-stream.h>
-#include <prio.h>
+#include <camel/camel-tcp-stream-raw.h>
 
 #define CAMEL_TCP_STREAM_SSL_TYPE     (camel_tcp_stream_ssl_get_type ())
 #define CAMEL_TCP_STREAM_SSL(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_SSL_TYPE, CamelTcpStreamSSL))
@@ -40,13 +39,13 @@ G_BEGIN_DECLS
 struct _CamelSession;
 
 struct _CamelTcpStreamSSL {
-	CamelTcpStream parent_object;
+	CamelTcpStreamRaw parent_object;
 
 	struct _CamelTcpStreamSSLPrivate *priv;
 };
 
 typedef struct {
-	CamelTcpStreamClass parent_class;
+	CamelTcpStreamRawClass parent_class;
 
 	/* virtual functions */
 



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