aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl_gnutls.c
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2012-12-24 20:17:37 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2012-12-24 20:17:37 +0100
commit9b672857d1d395307f1bfac988a347d724e13eee (patch)
tree0a453816334731fdda963a53579df85bf5adba57 /lib/ssl_gnutls.c
parentdef3650fba32bdcefd6985ef339f38c3e528b8fe (diff)
SSL session caching. You'd think that this makes Twitter stuff faster, except
Twitter webservers seem to do successful session resumes only sporadically.
Diffstat (limited to 'lib/ssl_gnutls.c')
-rw-r--r--lib/ssl_gnutls.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c
index 8c502969..b698e630 100644
--- a/lib/ssl_gnutls.c
+++ b/lib/ssl_gnutls.c
@@ -1,7 +1,7 @@
/********************************************************************\
* BitlBee -- An IRC to other IM-networks gateway *
* *
- * Copyright 2002-2011 Wilmer van der Gaast and others *
+ * Copyright 2002-2012 Wilmer van der Gaast and others *
\********************************************************************/
/* SSL module - GnuTLS version */
@@ -62,6 +62,8 @@ struct scd
gnutls_session_t session;
};
+static GHashTable *session_cache;
+
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 );
@@ -96,6 +98,8 @@ void ssl_init( void )
gnutls_global_set_log_level( 3 );
*/
+ session_cache = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free );
+
atexit( ssl_deinit );
}
@@ -103,6 +107,8 @@ static void ssl_deinit( void )
{
gnutls_global_deinit();
gnutls_certificate_free_credentials( xcred );
+ g_hash_table_destroy( session_cache );
+ session_cache = NULL;
}
void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
@@ -221,6 +227,45 @@ static int verify_certificate_callback( gnutls_session_t session )
return verifyret;
}
+struct ssl_session
+{
+ size_t size;
+ char data[];
+};
+
+static void ssl_cache_add( struct scd *conn )
+{
+ size_t data_size;
+ struct ssl_session *data;
+ char *hostname;
+
+ if( !conn->hostname ||
+ gnutls_session_get_data( conn->session, NULL, &data_size ) != 0 )
+ return;
+
+ data = g_malloc( sizeof( struct ssl_session ) + data_size );
+ if( gnutls_session_get_data( conn->session, data->data, &data->size ) != 0 )
+ {
+ g_free( data );
+ return;
+ }
+
+ hostname = g_strdup( conn->hostname );
+ g_hash_table_insert( session_cache, hostname, data );
+}
+
+static void ssl_cache_resume( struct scd *conn )
+{
+ struct ssl_session *data;
+
+ if( conn->hostname &&
+ ( data = g_hash_table_lookup( session_cache, conn->hostname ) ) )
+ {
+ gnutls_session_set_data( conn->session, data->data, data->size );
+ g_hash_table_remove( session_cache, conn->hostname );
+ }
+}
+
char *ssl_verify_strerror( int code )
{
GString *ret = g_string_new( "" );
@@ -279,6 +324,8 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
sock_make_nonblocking( conn->fd );
gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd );
+ ssl_cache_resume( conn );
+
return ssl_handshake( data, source, cond );
}
@@ -319,7 +366,8 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
{
/* For now we can't handle non-blocking perfectly everywhere... */
sock_make_blocking( conn->fd );
-
+
+ ssl_cache_add( conn );
conn->established = TRUE;
conn->func( conn->data, 0, conn, cond );
}