Mercurial > hg > freeDiameter
diff freeDiameter/sctps.c @ 155:30a7252cbb55
Cleanup connection cleanup sequence
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Tue, 19 Jan 2010 11:41:01 +0900 |
parents | a8aa7ea6d629 |
children | e2dc300819b3 |
line wrap: on
line diff
--- a/freeDiameter/sctps.c Tue Dec 22 15:53:13 2009 +0900 +++ b/freeDiameter/sctps.c Tue Jan 19 11:41:01 2010 +0900 @@ -109,7 +109,9 @@ TRACE_DEBUG(FULL, "Thread terminated"); return NULL; error: - CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); + if (!conn->cc_closing) { + CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); + } goto out; } @@ -133,7 +135,9 @@ CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */); error: - CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); + if (!cnx->cc_closing) { + CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); + } TRACE_DEBUG(FULL, "Thread terminated"); return NULL; } @@ -578,6 +582,71 @@ return 0; } +static void * bye_th(void * arg) +{ + struct sctps_ctx * ctx = (struct sctps_ctx *) arg; + TRACE_ENTRY("%p", arg); + + /* Set the thread name */ + { + char buf[48]; + snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket); + fd_log_threadname ( buf ); + } + + CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_WR), /* Continue */ ); + + /* Finish */ + return NULL; +} + +/* Initiate a "bye" on all stream pairs in paralel */ +void fd_sctps_bye(struct cnxctx * conn) +{ + uint16_t i; + + CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); + + /* End all TLS sessions, in parallel */ + for (i = 1; i < conn->cc_sctp_para.pairs; i++) { + CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break ); + } + for (--i; i > 0; --i) { + CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue ); + } +} + +/* After "bye" was sent on all streams, read from sessions until an error is received */ +void fd_sctps_waitthreadsterm(struct cnxctx * conn) +{ + uint16_t i; + + TRACE_ENTRY("%p", conn); + CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); + + for (i = 0; i < conn->cc_sctp_para.pairs; i++) { + if (conn->cc_sctps_data.array[i].thr != (pthread_t)NULL) { + CHECK_POSIX_DO( pthread_join(conn->cc_sctps_data.array[i].thr, NULL), /* continue */ ); + conn->cc_sctps_data.array[i].thr = (pthread_t)NULL; + } + } + return; +} + +/* Free gnutls resources of all sessions */ +void fd_sctps_gnutls_deinit_others(struct cnxctx * conn) +{ + uint16_t i; + + TRACE_ENTRY("%p", conn); + CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); + + for (i = 1; i < conn->cc_sctp_para.pairs; i++) { + gnutls_deinit(conn->cc_sctps_data.array[i].session); + } +} + + /* Stop all receiver threads */ void fd_sctps_stopthreads(struct cnxctx * conn) { @@ -592,26 +661,6 @@ return; } -static void * bye_th(void * arg) -{ - struct sctps_ctx * ctx = (struct sctps_ctx *) arg; - TRACE_ENTRY("%p", arg); - - /* Set the thread name */ - { - char buf[48]; - snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket); - fd_log_threadname ( buf ); - } - - CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_RDWR), /* Continue */ ); - - /* Finish */ - return arg; -} - - - /* Destroy a wrapper context */ void fd_sctps_destroy(struct cnxctx * conn) { @@ -622,14 +671,6 @@ /* Terminate all receiving threads in case we did not do it yet */ fd_sctps_stopthreads(conn); - /* End all TLS sessions, in parallel */ - for (i = 1; i < conn->cc_sctp_para.pairs; i++) { - CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break ); - } - for (--i; i > 0; --i) { - CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue ); - } -skip: /* Now, stop the demux thread */ CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );