[Freeswitch-svn] [commit] r2670 - in freeswitch/trunk/src: . mod/applications/mod_conference mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Tue Sep 12 18:24:40 EDT 2006


Author: anthm
Date: Tue Sep 12 18:24:39 2006
New Revision: 2670

Modified:
   freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/switch_core.c

Log:
add justinu's patch

Modified: freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	Tue Sep 12 18:24:39 2006
@@ -80,7 +80,8 @@
 	CFLAG_DYNAMIC = (1 << 1),
 	CFLAG_ENFORCE_MIN = (1 << 2),
 	CFLAG_DESTRUCT = (1 << 3),
-	CFLAG_LOCKED = (1 << 4)
+	CFLAG_LOCKED = (1 << 4),
+	CFLAG_ANSWERED = (1 << 5)
 } conf_flag_t;
 
 typedef enum {
@@ -127,6 +128,7 @@
 	char *bad_pin_sound;
 	char *profile_name;
 	uint32_t flags;
+	switch_call_cause_t bridge_hangup_cause;
 	switch_mutex_t *flag_mutex;
 	uint32_t rate;
 	uint32_t interval;
@@ -645,7 +647,13 @@
 
 		for(imember = conference->members; imember; imember = imember->next) {
 			switch_channel_t *channel = switch_core_session_get_channel(imember->session);
-			switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+			// add this little bit to preserve the bridge cause code in case of an early media call that
+			// never answers
+			if (switch_test_flag(conference, CFLAG_ANSWERED)) 
+				switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);	
+			else 	
+				// put actual cause code from outbound channel hangup here
+				switch_channel_hangup(channel, conference->bridge_hangup_cause);
 			switch_clear_flag_locked(imember, MFLAG_RUNNING);
 		}
 
@@ -698,12 +706,6 @@
 		return;
 	}
 
-	if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
-		/* Answer the channel */
-		switch_channel_answer(channel);
-	}
-
-	/* Prepare the write frame */
 	write_frame.data = data;
 	write_frame.buflen = sizeof(data);
 	write_frame.codec = &member->write_codec;
@@ -723,7 +725,20 @@
 		if (switch_core_session_dequeue_event(member->session, &event) == SWITCH_STATUS_SUCCESS) {
 			switch_event_destroy(&event);
 		}
-
+#if 1
+		if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+			// test to see if outbound channel has answered
+			if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound conference channel answered, setting CFLAG_ANSWERED");
+				switch_set_flag(member->conference, CFLAG_ANSWERED);
+			}
+		} else {
+			if (switch_test_flag(member->conference, CFLAG_ANSWERED) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CLFAG_ANSWERED set, answering inbound channel\n");
+				switch_channel_answer(channel);
+			}
+		}
+#endif
         if (switch_channel_has_dtmf(channel)) {
             switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
 
@@ -946,6 +961,15 @@
 	switch_clear_flag_locked(member, MFLAG_RUNNING);
 	switch_core_timer_destroy(&timer);
 
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel leaving conference, cause: %s\n",
+			switch_channel_cause2str(switch_channel_get_cause(channel)));
+
+	// if it's an outbound channel, store the release cause in the conference struct, we might need it
+	if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+		member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
+	}
+
 	/* Wait for the input thead to end */
 	while(switch_test_flag(member, MFLAG_ITHREAD)) {
 		switch_yield(1000);
@@ -2055,7 +2079,8 @@
 							 cid_name,
 							 cid_num,
 							 NULL) != SWITCH_STATUS_SUCCESS) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel!\n");
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create outgoing channel, cause: %s\n",
+				  switch_channel_cause2str(cause));
 		if (session) {
 			caller_channel = switch_core_session_get_channel(session);
 			switch_channel_hangup(caller_channel, cause);
@@ -2319,7 +2344,9 @@
 		if (conference_outcall(conference, session, bridgeto, 60, NULL, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
 			goto done;
 		}
-	}
+	} //else 	
+		// if we're not using "bridge:" set the conference answered flag
+		//switch_set_flag(conference, CFLAG_ANSWERED);
 
 
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Tue Sep 12 18:24:39 2006
@@ -532,14 +532,69 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+// map QSIG cause codes to SIP ala RFC4497
+static int hangup_cause_to_sip(switch_call_cause_t cause) {
+	switch (cause) {
+		case SWITCH_CAUSE_UNALLOCATED: 
+		case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
+		case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
+			return 404;
+		case SWITCH_CAUSE_USER_BUSY:
+			return 486;
+		case SWITCH_CAUSE_NO_USER_RESPONSE:
+			return 408;
+		case SWITCH_CAUSE_NO_ANSWER:
+			return 480;
+		case SWITCH_CAUSE_CALL_REJECTED:
+			return 603;
+		case SWITCH_CAUSE_NUMBER_CHANGED:
+			return 410;
+		case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
+			return 502;
+		case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
+			return 484;
+		case SWITCH_CAUSE_FACILITY_REJECTED:
+			return 501;
+		case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
+			return 480;
+		case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+		case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
+		case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
+		case SWITCH_CAUSE_SWITCH_CONGESTION:
+			return 503;
+		case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
+		case SWITCH_CAUSE_INCOMING_CALL_BARRED:
+		case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH: 
+			return 403;
+		case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL:
+			return 503;
+		case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL:
+			return 488;
+		case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
+			return 501;
+		case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
+			return 503;
+		case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
+			return 504;
+		default:
+			return 500;
+	}
+
+}
+
 static switch_status_t sofia_on_hangup(switch_core_session_t *session)
 {
 	private_object_t *tech_pvt;
 	switch_channel_t *channel = NULL;
+	switch_call_cause_t cause;
+	int sip_cause;
 
 	channel = switch_core_session_get_channel(session);
 	assert(channel != NULL);
 
+	cause = switch_channel_get_cause(channel);
+	sip_cause = hangup_cause_to_sip(cause);
+
 	tech_pvt = (private_object_t *) switch_core_session_get_private(session);
 	assert(tech_pvt != NULL);
 
@@ -547,14 +602,18 @@
 
 	su_home_deinit(tech_pvt->home);
 
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s hanging up, cause: %s, SIP response: %d\n", 
+			  switch_channel_get_name(channel), switch_channel_cause2str(cause), sip_cause);
 
-
 	if (tech_pvt->nh) {
 		if (!switch_test_flag(tech_pvt, TFLAG_BYE)) {
 			if (switch_test_flag(tech_pvt, TFLAG_ANS)) {
 				nua_bye(tech_pvt->nh, TAG_END());
 			} else {
-				nua_cancel(tech_pvt->nh, TAG_END());
+				if (switch_test_flag(tech_pvt, TFLAG_INBOUND)) 
+					nua_respond(tech_pvt->nh, sip_cause, NULL, TAG_END());
+				else 
+					nua_cancel(tech_pvt->nh, TAG_END());
 			}
 		}
 		nua_handle_bind(tech_pvt->nh, NULL);
@@ -565,8 +624,6 @@
 	switch_set_flag_locked(tech_pvt, TFLAG_BYE);
 	switch_clear_flag_locked(tech_pvt, TFLAG_IO);
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SOFIA HANGUP\n");
-
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -1198,6 +1255,57 @@
 	return match;
 }
 
+// map sip responses to QSIG cause codes ala RFC4497
+static switch_call_cause_t sip_cause_to_freeswitch(int status) {
+	switch (status) {
+		case 200:
+			return SWITCH_CAUSE_NORMAL_CLEARING;
+		case 401:
+		case 402: 
+		case 403:
+		case 407:
+		case 603:
+			return SWITCH_CAUSE_CALL_REJECTED;
+		case 404:
+		case 485:
+		case 604:	
+			return SWITCH_CAUSE_UNALLOCATED;
+		case 408: 
+		case 504:
+			return SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
+		case 410: 
+			return SWITCH_CAUSE_NUMBER_CHANGED;
+		case 413: 
+		case 414:
+		case 416:
+		case 420:
+		case 421:
+		case 423:
+		case 505:
+		case 513:
+			return SWITCH_CAUSE_INTERWORKING;
+		case 480:
+			return SWITCH_CAUSE_NO_USER_RESPONSE;
+		case 400:
+		case 481:
+		case 500:
+		case 503:
+			return SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE;
+		case 486:
+		case 600:
+			return SWITCH_CAUSE_USER_BUSY;
+		case 484:
+			return SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
+		case 488:
+		case 606:
+			return SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL;
+		case 502:
+			return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER;
+		default: 
+			return SWITCH_CAUSE_NORMAL_UNSPECIFIED;
+	}
+}
+
 static void sip_i_state(int status,
 						char const *phrase, 
 						nua_t *nua,
@@ -1362,7 +1470,7 @@
 	case nua_callstate_terminated:
 		if (session) {
 			switch_set_flag_locked(tech_pvt, TFLAG_BYE);
-			terminate_session(&session, SWITCH_CAUSE_NORMAL_CLEARING, __LINE__);
+			terminate_session(&session, sip_cause_to_freeswitch(status), __LINE__);
 		}
 		break;
 	}
@@ -1445,8 +1553,8 @@
 						   tagi_t        tags[])
 {
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event [%s] status [%d] [%s]\n",
-					  nua_event_name (event), status, phrase);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "channel [%s] event [%s] status [%d] [%s]\n",
+					  session ? switch_channel_get_name(switch_core_session_get_channel(session)) : "null",nua_event_name (event), status, phrase);
 	
 	switch (event) {
 	case nua_r_shutdown:    

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Tue Sep 12 18:24:39 2006
@@ -2372,7 +2372,7 @@
 static void switch_core_standard_on_hangup(switch_core_session_t *session)
 {
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HANGUP %s\n", switch_channel_get_name(session->channel));
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HANGUP %s, cause: %s\n", switch_channel_get_name(session->channel),switch_channel_cause2str(switch_channel_get_cause(session->channel)));
 
 }
 



More information about the Freeswitch-svn mailing list