Ignore:
Timestamp:
2005-12-16T17:58:00Z (15 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
12c6634, 4bfca70
Parents:
c4168f4
Message:

Non-blocking SSL handshakes for GnuTLS. The rest might come later, but is
slightly less important.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/ssl_gnutls.c

    rc4168f4 r701acdd4  
    2525
    2626#include <gnutls/gnutls.h>
     27#include <fcntl.h>
     28#include <unistd.h>
    2729#include "proxy.h"
    2830#include "ssl_client.h"
    2931#include "sock.h"
    3032#include "stdlib.h"
     33
     34int ssl_errno = 0;
    3135
    3236static gboolean initialized = FALSE;
     
    3842        int fd;
    3943        gboolean established;
     44        int inpa;
    4045       
    4146        gnutls_session session;
     
    4449
    4550static void ssl_connected( gpointer data, gint source, GaimInputCondition cond );
    46 
    4751
    4852
     
    5458        conn->func = func;
    5559        conn->data = data;
     60        conn->inpa = -1;
    5661       
    5762        if( conn->fd < 0 )
     
    7681}
    7782
     83static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond );
     84
    7885static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
    7986{
     
    8188       
    8289        if( source == -1 )
    83                 goto ssl_connected_failure;
     90        {
     91                conn->func( conn->data, NULL, cond );
     92               
     93                gnutls_deinit( conn->session );
     94                gnutls_certificate_free_credentials( conn->xcred );
     95               
     96                g_free( conn );
     97               
     98                return;
     99        }
    84100       
     101        sock_make_nonblocking( conn->fd );
    85102        gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd );
    86103       
    87         if( gnutls_handshake( conn->session ) < 0 )
    88                 goto ssl_connected_failure;
     104        ssl_handshake( data, source, cond );
     105}
     106
     107static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond )
     108{
     109        struct scd *conn = data;
     110        int st;
    89111       
    90         conn->established = TRUE;
    91         conn->func( conn->data, conn, cond );
    92         return;
     112        if( conn->inpa != -1 )
     113                gaim_input_remove( conn->inpa );
    93114       
    94 ssl_connected_failure:
    95         conn->func( conn->data, NULL, cond );
    96        
    97         gnutls_deinit( conn->session );
    98         gnutls_certificate_free_credentials( conn->xcred );
    99         if( source >= 0 ) closesocket( source );
    100         g_free( conn );
     115        if( ( st = gnutls_handshake( conn->session ) ) < 0 )
     116        {
     117                if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
     118                {
     119                        conn->inpa = gaim_input_add( conn->fd,
     120                                                     gnutls_record_get_direction( conn->session ) ?
     121                                                         GAIM_INPUT_WRITE : GAIM_INPUT_READ,
     122                                                     ssl_handshake, data );
     123                }
     124                else
     125                {
     126                        conn->func( conn->data, NULL, cond );
     127                       
     128                        gnutls_deinit( conn->session );
     129                        gnutls_certificate_free_credentials( conn->xcred );
     130                        closesocket( conn->fd );
     131                       
     132                        g_free( conn );
     133                }
     134        }
     135        else
     136        {
     137                /* For now we can't handle non-blocking perfectly everywhere... */
     138                sock_make_blocking( conn->fd );
     139               
     140                conn->established = TRUE;
     141                conn->func( conn->data, conn, cond );
     142        }
    101143}
    102144
     
    104146{
    105147        if( !((struct scd*)conn)->established )
    106                 return( 0 );
     148        {
     149                ssl_errno = SSL_NOHANDSHAKE;
     150                return( -1 );
     151        }
    107152       
    108153        return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) );
     154       
    109155}
    110156
     
    112158{
    113159        if( !((struct scd*)conn)->established )
    114                 return( 0 );
     160        {
     161                ssl_errno = SSL_NOHANDSHAKE;
     162                return( -1 );
     163        }
    115164       
    116165        return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) );
Note: See TracChangeset for help on using the changeset viewer.