[evolution-data-server/camel-socks-proxy] 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] Derive CamelTcpStreamSSL from CamelTcpStreamRaw
- Date: Thu, 15 Jul 2010 21:15:23 +0000 (UTC)
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]