[Freeswitch-svn] [commit] r2273 - freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip

Freeswitch SVN bennylp at freeswitch.org
Sat Aug 12 13:59:22 EDT 2006


Author: bennylp
Date: Sat Aug 12 13:59:21 2006
New Revision: 2273

Modified:
   freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c

Log:
As good as it gets: less crashes, less deadlocks

Modified: freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c
==============================================================================
--- freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c	(original)
+++ freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c	Sat Aug 12 13:59:21 2006
@@ -83,6 +83,7 @@
 
 	int max_calls;
 	int calls;
+	int thread_cnt;
 
 	int flags;
 	switch_hash_t *call_hash;
@@ -418,15 +419,17 @@
 
 	/* Hangup PJSIP call */
 	if (tech_pvt->sip_invite && tech_pvt->sip_invite->state < PJSIP_INV_STATE_DISCONNECTED) {
-		status = pjsip_inv_end_session( tech_pvt->sip_invite, 200, NULL, &txdata );
-		if( status == PJ_SUCCESS ) {
+		pjsip_dlg_inc_lock(tech_pvt->sip_dialog);
+		status = pjsip_inv_end_session( tech_pvt->sip_invite, PJSIP_SC_DECLINE, NULL, &txdata );
+		if( status == PJ_SUCCESS && txdata) {
 			add_server_header(txdata);
 			status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
 		}
 
 		if (status != PJ_SUCCESS) {
-			perror_(tech_pvt->sip_invite->dlg->obj_name, "Unable to hangup", status);
+			perror_(THIS_FILE, "Unable to hangup", status);
 		}
+		pjsip_dlg_dec_lock(tech_pvt->sip_dialog);
 	}
 
 	if (switch_test_flag( tech_pvt, TFLAG_USING_CODEC ) ) {
@@ -494,6 +497,9 @@
 	tech_pvt = switch_core_session_get_private( session );
 	assert( tech_pvt != NULL );
 
+	if ( tech_pvt->sip_invite == NULL )
+		return SWITCH_STATUS_SUCCESS;
+
 	PJ_LOG(4,(THIS_FILE, "* Answering call %s", tech_pvt->call_id));
 
 	if( !switch_test_flag( tech_pvt, TFLAG_ANSWERED ) &&
@@ -502,17 +508,17 @@
 		pjsip_tx_data *txdata;
 		pj_status_t status;
 
-		assert( tech_pvt->sip_invite != NULL );
 
 		PJ_LOG(4,(THIS_FILE, "* Sending 200 on INVITE to %s (%s)", 
 				  tech_pvt->call_id, switch_channel_get_name( channel ) ));
 
 		/* create SIP 200 with SDP */
 		status = pjsip_inv_answer( tech_pvt->sip_invite, 200, NULL, NULL, &txdata );
-		if( status != PJ_SUCCESS ) {
-			perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_answer error", status);
-
-			pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
+		if( status != PJ_SUCCESS || tech_pvt->sip_invite==NULL || txdata==NULL) {
+			if (tech_pvt->sip_invite) {
+				perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_answer error", status);
+				pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
+			}
 			switch_core_session_destroy( &session );
 			TRACE_((THIS_FILE, "LEAVE pjsip_answer_channel"));
 			return SWITCH_STATUS_GENERR;
@@ -540,6 +546,16 @@
 	struct private_object *tech_pvt;
 	switch_channel_t *channel;
 
+#if 0
+	pj_thread_desc tmp_desc;
+
+	if (!pj_thread_is_registered()) {
+		/* Kidz.. don't do this at home! */
+		pj_thread_t *thread;
+		pj_thread_register("kill%p", tmp_desc, &thread);
+	}
+#endif
+
 	TRACE_((THIS_FILE, "ENTER pjsip_kill_channel"));
 
 	assert( session != NULL );
@@ -698,6 +714,8 @@
 	if (switch_test_flag(tech_pvt, TFLAG_IO)) {
 		switch_status_t status;
 
+		if (tech_pvt->rtp_session == NULL)
+			return SWITCH_STATUS_FALSE;
 		assert(tech_pvt->rtp_session != NULL);
 		tech_pvt->read_frame.datalen = 0;
 
@@ -800,6 +818,10 @@
 		return SWITCH_STATUS_SUCCESS;
 	}
 
+	if (!tech_pvt->rtp_session) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
 	if (switch_test_flag(tech_pvt, TFLAG_BYE)) {
 		TRACE_((THIS_FILE, "switch_channel_hangup(%x) called by pjsip_write_frame()", channel));
 		switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
@@ -817,7 +839,9 @@
 	}
 
 	samples	= frames * tech_pvt->read_codec.implementation->samples_per_frame;
-	switch_rtp_write_frame( tech_pvt->rtp_session, frame, samples );
+	if (tech_pvt->rtp_session) {
+		switch_rtp_write_frame( tech_pvt->rtp_session, frame, samples );
+	}
 
 	switch_clear_flag_locked(tech_pvt, TFLAG_WRITING);
 	return status;
@@ -976,7 +1000,6 @@
 
 			sip_uri = pjsip_uri_get_uri(rxdata->msg_info.to->uri);
 			pj_strdup_with_null( dialog->pool, &destination, &sip_uri->user);
-			PJ_LOG(3,(dialog->obj_name, "Destination set to %s", destination.ptr));
 		} else {
 			destination = pj_str("unknown");
 		}
@@ -1281,18 +1304,16 @@
 	switch( inv->state )
 	{
 	case PJSIP_INV_STATE_DISCONNECTED:
-		/* Remove association between PJSIP call and channel, to prevent
-     * other channels from re-entering PJSIP for the context of this INVITE
-     * (which is guaranteed to cause deadlock!) 
-     */
 		pjsip_dlg_inc_lock(inv->dlg);
 
-		switch_mutex_lock(tech_pvt->flag_mutex);
-		inv->mod_data[globals.mod_app.id] = NULL;
-		tech_pvt->sip_invite = NULL;
-		tech_pvt->sip_dialog = NULL;
-	  switch_mutex_unlock(tech_pvt->flag_mutex);
+		//switch_mutex_lock(tech_pvt->flag_mutex);
+		//inv->mod_data[globals.mod_app.id] = NULL;
+		//tech_pvt->sip_invite = NULL;
+		//tech_pvt->sip_dialog = NULL;
+	  	//switch_mutex_unlock(tech_pvt->flag_mutex);
 
+		pjsip_on_hangup(session);
+
 		PJ_LOG(4,(THIS_FILE, "* Call %s (%s) has been disconnected", tech_pvt->call_id,
 									switch_channel_get_name( channel ) ));
 
@@ -1382,6 +1403,10 @@
 	int ms, rate;
 	pj_sockaddr addr;
 
+
+//#define ASSERT_FAIL()		assert(!"call_on_media_update failed");
+#define ASSERT_FAIL()
+
 	TRACE_((THIS_FILE, "ENTER call_on_media_update"));
 
 	tech_pvt = inv->mod_data[globals.mod_app.id];
@@ -1414,6 +1439,7 @@
 		PJ_LOG(1,(THIS_FILE, "SDP negotiation failed for call %s, reason: %s", tech_pvt->call_id, tmp ));
 		switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
 		TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
+		ASSERT_FAIL()
 		return;
 	}
 
@@ -1470,6 +1496,7 @@
 		switch_clear_flag_locked( tech_pvt, TFLAG_IO );
 		switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
 		TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
+		ASSERT_FAIL()
 		return;
 	}
 
@@ -1488,6 +1515,7 @@
 		perror_(THIS_FILE, "Failed to initialize read codec", -1);
 		switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
 		TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
+		ASSERT_FAIL()
 		return;
 	}
 
@@ -1499,6 +1527,7 @@
 		perror_(THIS_FILE, "ERROR: Failed to initialize write codec", -1 );
 		switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
 		TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
+		ASSERT_FAIL()
 		return;
 	}
 
@@ -1797,8 +1826,10 @@
 	}
 
 	switch_mutex_lock(tech_pvt->flag_mutex);
-	switch_rtp_destroy( &tech_pvt->rtp_session );
-	tech_pvt->rtp_session = NULL;
+	if (tech_pvt->rtp_session) {
+		switch_rtp_destroy( &tech_pvt->rtp_session );
+		tech_pvt->rtp_session = NULL;
+	}
 	switch_mutex_unlock(tech_pvt->flag_mutex);
 	
 	TRACE_((THIS_FILE, "LEAVE stop_rtp"));
@@ -1913,6 +1944,9 @@
 					}
 				}
 			}
+			else if (!strcmp(var, "thread-cnt")) {
+				profile->thread_cnt = atoi( val );
+			}
 			else {
 				switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown option %s (ignored)\n", var );
 			}
@@ -2051,21 +2085,25 @@
 /* PJSIP worker thread */
 static int pjsip_worker_thread(void *arg)
 {
+	PJ_LOG(3,(THIS_FILE, "PJSIP Worker Thread starting.."));
+
 	while ( globals.running > 0 ) {
 		pj_time_val timeout = { 1, 0 };
 		TRACE_((THIS_FILE, "ENTER pjsip_endpt_handle_events"));
 		pjsip_endpt_handle_events( globals.sip_endpt, &timeout );
 		TRACE_((THIS_FILE, "LEAVE pjsip_endpt_handle_events"));
 	}
+
+
+	PJ_LOG(3,(THIS_FILE, "PJSIP Worker Thread quitting.."));
 	return 0;
 }
 
 
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
 {
-	enum { WORKER_COUNT=0 };
 	pj_thread_t *worker_threads[16];
-	int i;
+	int thread_cnt=0, i;
 	switch_hash_index_t *p_entry;
 	pj_status_t status;
 
@@ -2133,6 +2171,9 @@
 		switch_hash_this( p_entry, NULL, NULL, &val );
 		profile = val;
 
+		if (profile->thread_cnt > thread_cnt)
+			thread_cnt = profile->thread_cnt;
+
 		if( switch_test_flag( profile, PFLAG_TRANSPORT_UDP ) ) {
 			pjsip_transport *transport;
 
@@ -2237,7 +2278,7 @@
 	globals.running = 1;
 
 	/* Create PJSIP from worker threads */
-	for (i=0; i<WORKER_COUNT; ++i) {
+	for (i=0; i<thread_cnt; ++i) {
 		status = pj_thread_create(pjsip_pool, "sip%p", &pjsip_worker_thread, NULL, 0, 0, &worker_threads[i]);
 		if (status != PJ_SUCCESS) {
 			perror_(THIS_FILE, "Unable to create thread!", status);
@@ -2257,7 +2298,7 @@
 	globals.running = 0;
 
 	/* Wait for all worker threads to quit */
-	for (i=0; i<WORKER_COUNT; ++i) {
+	for (i=0; i<thread_cnt; ++i) {
 		status = pj_thread_join(worker_threads[i]);
 	}
 



More information about the Freeswitch-svn mailing list