@ -2623,12 +2623,31 @@ static int xmpp_client_request_tls(struct ast_xmpp_client *client, struct ast_xm
# endif
}
# ifdef HAVE_OPENSSL
static char * openssl_error_string ( void )
{
char * buf = NULL , * ret ;
size_t len ;
BIO * bio = BIO_new ( BIO_s_mem ( ) ) ;
ERR_print_errors ( bio ) ;
len = BIO_get_mem_data ( bio , & buf ) ;
ret = ast_calloc ( 1 , len + 1 ) ;
if ( ret ) {
memcpy ( ret , buf , len ) ;
}
BIO_free ( bio ) ;
return ret ;
}
# endif
/*! \brief Internal function called when we receive a response to our TLS initiation request */
static int xmpp_client_requested_tls ( struct ast_xmpp_client * client , struct ast_xmpp_client_config * cfg , int type , iks * node )
{
# ifdef HAVE_OPENSSL
int sock ;
long ssl_opts ;
char * err ;
# endif
if ( ! strcmp ( iks_name ( node ) , " success " ) ) {
@ -2664,7 +2683,7 @@ static int xmpp_client_requested_tls(struct ast_xmpp_client *client, struct ast_
goto failure ;
}
if ( ! SSL_connect ( client - > ssl_session ) ) {
if ( SSL_connect ( client - > ssl_session ) < = 0 ) {
goto failure ;
}
@ -2684,7 +2703,10 @@ static int xmpp_client_requested_tls(struct ast_xmpp_client *client, struct ast_
return 0 ;
failure :
ast_log ( LOG_ERROR , " TLS connection for client '%s' cannot be established. OpenSSL initialization failed. \n " , client - > name ) ;
err = openssl_error_string ( ) ;
ast_log ( LOG_ERROR , " TLS connection for client '%s' cannot be established. "
" OpenSSL initialization failed: %s \n " , client - > name , err ) ;
ast_free ( err ) ;
return - 1 ;
# endif
}
@ -3559,6 +3581,7 @@ int ast_xmpp_client_disconnect(struct ast_xmpp_client *client)
{
if ( ( client - > thread ! = AST_PTHREADT_NULL ) & & ! pthread_equal ( pthread_self ( ) , client - > thread ) ) {
xmpp_client_change_state ( client , XMPP_STATE_DISCONNECTING ) ;
pthread_cancel ( client - > thread ) ;
pthread_join ( client - > thread , NULL ) ;
client - > thread = AST_PTHREADT_NULL ;
}
@ -3738,11 +3761,26 @@ static int xmpp_client_receive(struct ast_xmpp_client *client, unsigned int time
return IKS_OK ;
}
static void sleep_with_backoff ( unsigned int * sleep_time )
{
/* We're OK with our thread dying here */
pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE , NULL ) ;
sleep ( * sleep_time ) ;
* sleep_time = MIN ( 60 , * sleep_time * 2 ) ;
pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE , NULL ) ;
}
/*! \brief XMPP client connection thread */
static void * xmpp_client_thread ( void * data )
{
struct ast_xmpp_client * client = data ;
int res = IKS_NET_RWERR ;
unsigned int sleep_time = 1 ;
/* We only allow cancellation while sleeping */
pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE , NULL ) ;
do {
if ( client - > state = = XMPP_STATE_DISCONNECTING ) {
@ -3753,7 +3791,7 @@ static void *xmpp_client_thread(void *data)
if ( res = = IKS_NET_RWERR | | client - > timeout = = 0 ) {
ast_debug ( 3 , " [%s] Connecting \n " , client - > name ) ;
if ( ( res = xmpp_client_reconnect ( client ) ) ! = IKS_OK ) {
sleep ( 4 ) ;
sleep _with_backoff( & sleep_time ) ;
res = IKS_NET_RWERR ;
}
continue ;
@ -3792,6 +3830,8 @@ static void *xmpp_client_thread(void *data)
}
} else if ( res = = IKS_NET_RWERR ) {
ast_log ( LOG_WARNING , " [%s] Socket read error \n " , client - > name ) ;
ast_xmpp_client_disconnect ( client ) ;
sleep_with_backoff ( & sleep_time ) ;
} else if ( res = = IKS_NET_NOSOCK ) {
ast_log ( LOG_WARNING , " [%s] No socket \n " , client - > name ) ;
} else if ( res = = IKS_NET_NOCONN ) {
@ -3804,6 +3844,8 @@ static void *xmpp_client_thread(void *data)
ast_log ( LOG_WARNING , " [%s] Dropped? \n " , client - > name ) ;
} else if ( res = = IKS_NET_UNKNOWN ) {
ast_debug ( 5 , " [%s] Unknown \n " , client - > name ) ;
} else if ( res = = IKS_OK ) {
sleep_time = 1 ;
}
} while ( 1 ) ;