[evolution-data-server/camel-socks-proxy-master] Derive CamelTcpStreamSSL from CamelTcpStreamRaw
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/camel-socks-proxy-master] Derive CamelTcpStreamSSL from CamelTcpStreamRaw
- Date: Wed, 28 Jul 2010 21:42:45 +0000 (UTC)
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]