Index: lib/ssl_gnutls.c
===================================================================
--- lib/ssl_gnutls.c	(revision 93b7bd4373c7c020f37fb96b547b5eda99daf547)
+++ lib/ssl_gnutls.c	(revision f920d9eb003541245e0fc32a381447cbba8fbea5)
@@ -108,7 +108,5 @@
 	{
 		conn->func( conn->data, NULL, cond );
-		
 		g_free( conn );
-		
 		return FALSE;
 	}
Index: lib/ssl_openssl.c
===================================================================
--- lib/ssl_openssl.c	(revision 93b7bd4373c7c020f37fb96b547b5eda99daf547)
+++ lib/ssl_openssl.c	(revision f920d9eb003541245e0fc32a381447cbba8fbea5)
@@ -53,4 +53,6 @@
 
 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
+static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond );
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
 
 
@@ -58,15 +60,56 @@
 {
 	struct scd *conn = g_new0( struct scd, 1 );
-	SSL_METHOD *meth;
 	
 	conn->fd = proxy_connect( host, port, ssl_connected, conn );
 	conn->func = func;
 	conn->data = data;
+	conn->inpa = -1;
 	
 	if( conn->fd < 0 )
 	{
 		g_free( conn );
-		return( NULL );
-	}
+		return NULL;
+	}
+	
+	return conn;
+}
+
+void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+{
+	struct scd *conn = g_new0( struct scd, 1 );
+	
+	conn->fd = fd;
+	conn->func = func;
+	conn->data = data;
+	conn->inpa = -1;
+	
+	/* This function should be called via a (short) timeout instead of
+	   directly from here, because these SSL calls are *supposed* to be
+	   *completely* asynchronous and not ready yet when this function
+	   (or *_connect, for examle) returns. Also, errors are reported via
+	   the callback function, not via this function's return value.
+	   
+	   In short, doing things like this makes the rest of the code a lot
+	   simpler. */
+	
+	b_timeout_add( 1, ssl_starttls_real, conn );
+	
+	return conn;
+}
+
+static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	
+	return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE );
+}
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	SSL_METHOD *meth;
+	
+	if( source == -1 )
+		goto ssl_connected_failure;
 	
 	if( !initialized )
@@ -79,27 +122,9 @@
 	conn->ssl_ctx = SSL_CTX_new( meth );
 	if( conn->ssl_ctx == NULL )
-	{
-		conn->fd = -1;
-		return( NULL );
-	}
+		goto ssl_connected_failure;
 	
 	conn->ssl = SSL_new( conn->ssl_ctx );
 	if( conn->ssl == NULL )
-	{
-		conn->fd = -1;
-		return( NULL );
-	}
-	
-	return( conn );
-}
-
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	
-	if( source == -1 )
-		return ssl_handshake( data, -1, cond );
+		goto ssl_connected_failure;
 	
 	/* We can do at least the handshake with non-blocking I/O */
@@ -108,4 +133,22 @@
 	
 	return ssl_handshake( data, source, cond );
+
+ssl_connected_failure:
+	conn->func( conn->data, NULL, cond );
+	
+	if( conn->ssl )
+	{
+		SSL_shutdown( conn->ssl );
+		SSL_free( conn->ssl );
+	}
+	if( conn->ssl_ctx )
+	{
+		SSL_CTX_free( conn->ssl_ctx );
+	}
+	if( source >= 0 ) closesocket( source );
+	g_free( conn );
+	
+	return FALSE;
+
 }	
 
@@ -119,5 +162,16 @@
 		conn->lasterr = SSL_get_error( conn->ssl, st );
 		if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
-			goto ssl_connected_failure;
+		{
+			conn->func( conn->data, NULL, cond );
+			
+			SSL_shutdown( conn->ssl );
+			SSL_free( conn->ssl );
+			SSL_CTX_free( conn->ssl_ctx );
+			
+			if( source >= 0 ) closesocket( source );
+			g_free( conn );
+			
+			return FALSE;
+		}
 		
 		conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
@@ -129,21 +183,4 @@
 	conn->func( conn->data, conn, cond );
 	return FALSE;
-	
-ssl_connected_failure:
-	conn->func( conn->data, NULL, cond );
-	
-	if( conn->ssl )
-	{
-		SSL_shutdown( conn->ssl );
-		SSL_free( conn->ssl );
-	}
-	if( conn->ssl_ctx )
-	{
-		SSL_CTX_free( conn->ssl_ctx );
-	}
-	if( source >= 0 ) closesocket( source );
-	g_free( conn );
-	
-	return FALSE;
 }
 
