diff options
| -rw-r--r-- | protocols/oscar/conn.c | 4 | ||||
| -rw-r--r-- | protocols/proxy.c | 14 | ||||
| -rw-r--r-- | protocols/ssl_bogus.c | 2 | ||||
| -rw-r--r-- | protocols/ssl_client.h | 6 | ||||
| -rw-r--r-- | protocols/ssl_gnutls.c | 81 | ||||
| -rw-r--r-- | protocols/ssl_nss.c | 2 | ||||
| -rw-r--r-- | protocols/ssl_openssl.c | 2 | ||||
| -rw-r--r-- | sock.h | 2 | 
8 files changed, 84 insertions, 29 deletions
| diff --git a/protocols/oscar/conn.c b/protocols/oscar/conn.c index 0155e5bc..77ffd50f 100644 --- a/protocols/oscar/conn.c +++ b/protocols/oscar/conn.c @@ -626,9 +626,7 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn)  		return -1;  	} -#ifndef _WIN32 -	fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ -#endif +	sock_make_blocking(conn->fd);  	conn->status &= ~AIM_CONN_STATUS_INPROGRESS; diff --git a/protocols/proxy.c b/protocols/proxy.c index 0546f2d7..c658a163 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -132,8 +132,8 @@ static void gaim_io_connected(gpointer data, gint source, GaimInputCondition con  		}  		return;  	} -	fcntl(source, F_SETFL, 0);  #endif +	sock_make_blocking(source);  	gaim_input_remove(phb->inpa);  	if( phb->proxy_func )  		phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ); @@ -228,9 +228,7 @@ static void http_canwrite(gpointer data, gint source, GaimInputCondition cond)  		g_free(phb);  		return;  	} -#ifdef F_SETFL -	fcntl(source, F_SETFL, 0); -#endif +	sock_make_blocking(source);  	g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port,  		   phb->host, phb->port); @@ -321,9 +319,7 @@ static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond)  		g_free(phb);  		return;  	} -#ifdef F_SETFL -	fcntl(source, F_SETFL, 0); -#endif +	sock_make_blocking(source);  	/* XXX does socks4 not support host name lookups by the proxy? */  	if (!(hp = gethostbyname(phb->host))) { @@ -508,9 +504,7 @@ static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond)  		g_free(phb);  		return;  	} -#ifdef F_SETFL -	fcntl(source, F_SETFL, 0); -#endif +	sock_make_blocking(source);  	i = 0;  	buf[0] = 0x05;		/* SOCKS version 5 */ diff --git a/protocols/ssl_bogus.c b/protocols/ssl_bogus.c index 226997db..1ee0df4c 100644 --- a/protocols/ssl_bogus.c +++ b/protocols/ssl_bogus.c @@ -25,6 +25,8 @@  #include "ssl_client.h" +int ssl_errno; +  void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )  {  	return( NULL ); diff --git a/protocols/ssl_client.h b/protocols/ssl_client.h index a829a7b1..719cd0c4 100644 --- a/protocols/ssl_client.h +++ b/protocols/ssl_client.h @@ -26,6 +26,12 @@  #include <glib.h>  #include "proxy.h" +#define SSL_OK            0 +#define SSL_NOHANDSHAKE   1 +#define SSL_AGAIN         2 + +extern int ssl_errno; +  typedef void (*SslInputFunction)(gpointer, void*, GaimInputCondition);  G_MODULE_EXPORT void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ); diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c index 535d126e..c2eb6906 100644 --- a/protocols/ssl_gnutls.c +++ b/protocols/ssl_gnutls.c @@ -24,11 +24,15 @@  */  #include <gnutls/gnutls.h> +#include <fcntl.h> +#include <unistd.h>  #include "proxy.h"  #include "ssl_client.h"  #include "sock.h"  #include "stdlib.h" +int ssl_errno = 0; +  static gboolean initialized = FALSE;  struct scd @@ -37,6 +41,7 @@ struct scd  	gpointer data;  	int fd;  	gboolean established; +	int inpa;  	gnutls_session session;  	gnutls_certificate_credentials xcred; @@ -45,7 +50,6 @@ struct scd  static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); -  void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )  {  	struct scd *conn = g_new0( struct scd, 1 ); @@ -53,6 +57,7 @@ void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )  	conn->fd = proxy_connect( host, port, ssl_connected, conn );  	conn->func = func;  	conn->data = data; +	conn->inpa = -1;  	if( conn->fd < 0 )  	{ @@ -75,43 +80,87 @@ void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )  	return( conn );  } +static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ); +  static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )  {  	struct scd *conn = data;  	if( source == -1 ) -		goto ssl_connected_failure; +	{ +		conn->func( conn->data, NULL, cond ); +		 +		gnutls_deinit( conn->session ); +		gnutls_certificate_free_credentials( conn->xcred ); +		 +		g_free( conn ); +		 +		return; +	} +	sock_make_nonblocking( conn->fd );  	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); -	if( gnutls_handshake( conn->session ) < 0 ) -		goto ssl_connected_failure; -	 -	conn->established = TRUE; -	conn->func( conn->data, conn, cond ); -	return; +	ssl_handshake( data, source, cond ); +} + +static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) +{ +	struct scd *conn = data; +	int st; -ssl_connected_failure: -	conn->func( conn->data, NULL, cond ); +	if( conn->inpa != -1 ) +		gaim_input_remove( conn->inpa ); -	gnutls_deinit( conn->session ); -	gnutls_certificate_free_credentials( conn->xcred ); -	if( source >= 0 ) closesocket( source ); -	g_free( conn ); +	if( ( st = gnutls_handshake( conn->session ) ) < 0 ) +	{ +		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) +		{ +			conn->inpa = gaim_input_add( conn->fd, +			                             gnutls_record_get_direction( conn->session ) ? +			                                 GAIM_INPUT_WRITE : GAIM_INPUT_READ, +			                             ssl_handshake, data ); +		} +		else +		{ +			conn->func( conn->data, NULL, cond ); +			 +			gnutls_deinit( conn->session ); +			gnutls_certificate_free_credentials( conn->xcred ); +			closesocket( conn->fd ); +			 +			g_free( conn ); +		} +	} +	else +	{ +		/* For now we can't handle non-blocking perfectly everywhere... */ +		sock_make_blocking( conn->fd ); +		 +		conn->established = TRUE; +		conn->func( conn->data, conn, cond ); +	}  }  int ssl_read( void *conn, char *buf, int len )  {  	if( !((struct scd*)conn)->established ) -		return( 0 ); +	{ +		ssl_errno = SSL_NOHANDSHAKE; +		return( -1 ); +	}  	return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) ); +	  }  int ssl_write( void *conn, const char *buf, int len )  {  	if( !((struct scd*)conn)->established ) -		return( 0 ); +	{ +		ssl_errno = SSL_NOHANDSHAKE; +		return( -1 ); +	}  	return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) );  } diff --git a/protocols/ssl_nss.c b/protocols/ssl_nss.c index 7c5f5637..d28983fc 100644 --- a/protocols/ssl_nss.c +++ b/protocols/ssl_nss.c @@ -38,6 +38,8 @@  #include <secerr.h>  #include <sslerr.h> +int ssl_errno = 0; +  static gboolean initialized = FALSE;  struct scd diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index d2a7e1fe..bf87ab73 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -34,6 +34,8 @@  #include "ssl_client.h"  #include "sock.h" +int ssl_errno = 0; +  static gboolean initialized = FALSE;  struct scd @@ -5,6 +5,7 @@  #include <arpa/inet.h>  #include <netdb.h>  #define sock_make_nonblocking(fd) fcntl(fd, F_SETFL, O_NONBLOCK) +#define sock_make_blocking(fd) fcntl(fd, F_SETFL, 0)  #define sockerr_again() (errno == EINPROGRESS || errno == EINTR)  #define closesocket(a) close(a)  #else @@ -21,6 +22,7 @@  # define umask _umask  # define mode_t int  # define sock_make_nonblocking(fd) { int non_block = 1; ioctlsocket(fd, FIONBIO, &non_block); } +# define sock_make_blocking(fd) { int non_block = 0; ioctlsocket(fd, FIONBIO, &non_block); }  # define sockerr_again() (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK)  # define ETIMEDOUT WSAETIMEDOUT  # define sleep(a) Sleep(a*1000) | 
