[asterisk-commits] moy: branch moy/mfcr2-1.4 r172068 - in /team/moy/mfcr2-1.4: channels/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 28 15:09:59 CST 2009


Author: moy
Date: Wed Jan 28 15:09:58 2009
New Revision: 172068

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=172068
Log:
added mfcr2_accept_on_offer experimental option

Modified:
    team/moy/mfcr2-1.4/channels/chan_dahdi.c
    team/moy/mfcr2-1.4/configs/chan_dahdi.conf.sample

Modified: team/moy/mfcr2-1.4/channels/chan_dahdi.c
URL: http://svn.digium.com/svn-view/asterisk/team/moy/mfcr2-1.4/channels/chan_dahdi.c?view=diff&rev=172068&r1=172067&r2=172068
==============================================================================
--- team/moy/mfcr2-1.4/channels/chan_dahdi.c (original)
+++ team/moy/mfcr2-1.4/channels/chan_dahdi.c Wed Jan 28 15:09:58 2009
@@ -320,6 +320,7 @@
 static int mfcr2_cur_context_index = 0;
 static int mfcr2_cur_call_files = 0;
 static int mfcr2_cur_allow_collect_calls = 0;
+static int mfcr2_cur_accept_on_offer = 1;
 static int mfcr2_cur_charge_calls = 1;
 static int mfcr2_cur_forced_release = 0;
 static int mfcr2_cur_double_answer = 0;
@@ -625,12 +626,14 @@
 	openr2_chan_t *r2chan;
 	openr2_calling_party_category_t mfcr2_recvd_category;
 	openr2_calling_party_category_t mfcr2_category;
+	int mfcr2_accept_on_offer;
 	int mfcr2_charge_calls;
 	int mfcr2_allow_collect_calls;
 	int mfcr2_forced_release;
 	int mfcr2_dnis_index;
 	int mfcr2_ani_index;
 	int mfcr2_dnis_matched;
+	int mfcr2_call_accepted;
 #endif
 	int polarity;
 	int dsp_features;
@@ -989,6 +992,7 @@
 	p->mfcr2_ani_index = 0;
 	p->mfcr2_dnis_index = 0;
 	p->mfcr2_dnis_matched = 0;
+	p->mfcr2_call_accepted = 0;
 	ast_mutex_unlock(&p->lock);
 	ast_log(LOG_NOTICE, "New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
 }
@@ -1035,9 +1039,28 @@
 	ast_mutex_unlock(&p->lock);
 }
 
+static void dahdi_r2_update_monitor_count(struct zt_mfcr2 *mfcr2, int increment)
+{
+	ast_mutex_lock(&mfcr2->monitored_count_lock);
+	if (increment) {
+		mfcr2->monitored_count++;
+		if (mfcr2->monitored_count == 1) {
+			ast_log(LOG_DEBUG, "At least one device needs monitoring, let's wake up that lazy bastard.\n");
+			ast_cond_signal(&mfcr2->do_monitor);
+		}
+	} else {
+		mfcr2->monitored_count--;
+		if (mfcr2->monitored_count < 0) {
+			ast_log(LOG_ERROR, "wtf? we have a bug here!.\n");
+		}
+	}
+	ast_mutex_unlock(&mfcr2->monitored_count_lock);
+}
+
 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
 {
 	struct dahdi_pvt *p;
+	struct ast_channel *c;
 	ast_log(LOG_NOTICE, "MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 
 			openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
 	p = openr2_chan_get_client_data(r2chan);
@@ -1066,9 +1089,23 @@
 				p->channel, p->exten, p->context);
 		openr2_chan_disconnect_call(r2chan, OR2_CAUSE_UNALLOCATED_NUMBER);
 	} else {
-		if (p->mfcr2_charge_calls) {
+		/* if the user does not want to accept on offer, then we should launch the PBX thread now */
+		if (!p->mfcr2_accept_on_offer) {
+			c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
+			if (c) {
+				dahdi_r2_update_monitor_count(p->mfcr2, 0);
+				pbx_builtin_setvar_helper(c, "MFCR2_CATEGORY", openr2_proto_get_category_string(p->mfcr2_recvd_category));
+				/* Don't disable reading since we still need to generate MF tone to accept
+				   the call or reject it and detect the tone off condition of the other end */
+			} else {
+				ast_log(LOG_WARNING, "Unable to start PBX on chan %d\n", p->channel);
+				openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER);
+			}
+		} else if (p->mfcr2_charge_calls) {
+			ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
 			openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
 		} else {
+			ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
 			openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
 		}	
 	}	
@@ -1083,24 +1120,6 @@
 	ast_mutex_unlock(&p->lock);
 }
 
-static void dahdi_r2_update_monitor_count(struct zt_mfcr2 *mfcr2, int increment)
-{
-	ast_mutex_lock(&mfcr2->monitored_count_lock);
-	if (increment) {
-		mfcr2->monitored_count++;
-		if (mfcr2->monitored_count == 1) {
-			ast_log(LOG_DEBUG, "At least one device needs monitoring, let's wake up that lazy bastard.\n");
-			ast_cond_signal(&mfcr2->do_monitor);
-		}
-	} else {
-		mfcr2->monitored_count--;
-		if (mfcr2->monitored_count < 0) {
-			ast_log(LOG_ERROR, "wtf? we have a bug here!.\n");
-		}
-	}
-	ast_mutex_unlock(&mfcr2->monitored_count_lock);
-}
-
 static void dahdi_enable_ec(struct dahdi_pvt *p);
 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
 {
@@ -1109,18 +1128,29 @@
 	ast_log(LOG_NOTICE, "MFC/R2 call has been accepted on chan %d\n", openr2_chan_get_number(r2chan));
 	p = openr2_chan_get_client_data(r2chan);
 	dahdi_enable_ec(p);
+	p->mfcr2_call_accepted = 1;
 	if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
+		/* if accept on offer is not set, it means at this point the PBX thread is already
+		   launched and therefore this callback is being executed in the PBX thread rather than
+		   the monitor thread, don't launch any other thread, just disable the R2 reading and
+		   answer the call */
+		if (!p->mfcr2_accept_on_offer) {
+			openr2_chan_disable_read(r2chan);
+			ast_log(LOG_NOTICE, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
+			openr2_chan_answer_call(r2chan);
+			return;
+		}
 		c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
 		if (c) {
 			dahdi_r2_update_monitor_count(p->mfcr2, 0);
 			/* chan_dahdi will take care of reading from now on, tell the library to forget about it */
 			openr2_chan_disable_read(r2chan);
+			pbx_builtin_setvar_helper(c, "MFCR2_CATEGORY", openr2_proto_get_category_string(p->mfcr2_recvd_category));
 		} else {
 			ast_log(LOG_WARNING, "Unable to start PBX on chan %d\n", p->channel);
 			openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER);
 			return;
 		}
-		pbx_builtin_setvar_helper(c, "MFCR2_CATEGORY", openr2_proto_get_category_string(p->mfcr2_recvd_category));
 	} else {
 		ast_log(LOG_NOTICE, "Call accepted on forward channel %d\n", p->channel);
 		p->subs[SUB_REAL].needringing = 1;
@@ -3005,6 +3035,46 @@
 }
 #endif
 
+#ifdef HAVE_OPENR2
+static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
+{
+	openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
+	switch (cause) {
+	case AST_CAUSE_USER_BUSY:
+	case AST_CAUSE_CALL_REJECTED:
+	case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
+		r2cause = OR2_CAUSE_BUSY_NUMBER;
+		break;
+
+	case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+	case AST_CAUSE_SWITCH_CONGESTION:
+		r2cause = OR2_CAUSE_NETWORK_CONGESTION;
+		break;
+
+	case AST_CAUSE_UNALLOCATED:
+		r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
+		break;
+
+	case AST_CAUSE_NETWORK_OUT_OF_ORDER:
+	case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
+		r2cause = OR2_CAUSE_OUT_OF_ORDER;
+		break;
+
+	case AST_CAUSE_NO_ANSWER:
+	case AST_CAUSE_NO_USER_RESPONSE:
+		r2cause = OR2_CAUSE_NO_ANSWER;
+		break;
+
+	default:
+		r2cause = OR2_CAUSE_NORMAL_CLEARING;
+		break;
+	}
+	ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 
+			r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
+	return r2cause;
+}
+#endif
+
 static int dahdi_hangup(struct ast_channel *ast)
 {
 	int res;
@@ -3184,10 +3254,16 @@
 #ifdef HAVE_OPENR2
 		if (p->mfcr2) {
 			ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
+			ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
 			if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
 				openr2_chan_disconnect_call(p->r2chan, OR2_CAUSE_FORCED_RELEASE);
 			} else {
-				openr2_chan_disconnect_call(p->r2chan, OR2_CAUSE_NORMAL_CLEARING);
+				const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
+				int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
+				openr2_call_disconnect_cause_t r2cause = r2cause_user
+								       ? dahdi_ast_cause_to_r2_cause(r2cause_user)
+								       : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
+				openr2_chan_disconnect_call(p->r2chan, r2cause);
 			}
 			dahdi_r2_update_monitor_count(p->mfcr2, 1);
 		}	
@@ -3426,8 +3502,20 @@
 #endif
 #ifdef HAVE_OPENR2
 	case SIG_MFCR2:
-		ast_log(LOG_DEBUG, "Accepting MFC/R2 call on chan %d\n", p->channel);
-		openr2_chan_answer_call(p->r2chan);
+		if (!p->mfcr2_accept_on_offer) {
+			/* the call was not accepted on offer, so it must be accepted now before answering,
+			   the answer will be executed when the callback on_call_accepted is executed */
+			if (p->mfcr2_charge_calls) {
+				ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
+				openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
+			} else {
+				ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
+				openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
+			}
+		} else {
+			ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
+			openr2_chan_answer_call(p->r2chan);
+		}
 		break;
 #endif
 	case 0:
@@ -5712,8 +5800,15 @@
 	int func = DAHDI_FLASH;
 	ast_mutex_lock(&p->lock);
 	index = dahdi_get_index(chan, p, 0);
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
+	ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
+#ifdef HAVE_OPENR2
+	if (p->mfcr2 && !p->mfcr2_call_accepted) {
+		ast_mutex_unlock(&p->lock);
+		/* if this an R2 call and the call is not yet accepted we don't want the 
+		   tone indications to mess up with the MF tones */
+		return 0;
+	}
+#endif
 	if (index == SUB_REAL) {
 		switch (condition) {
 		case AST_CONTROL_BUSY:
@@ -8148,6 +8243,7 @@
 					tmp->mfcr2_category = mfcr2_cur_category;
 					tmp->mfcr2 = dahdi_r2;
 					tmp->mfcr2call = 0;
+					tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
 					tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
 					tmp->mfcr2_ani_index = 0;
 					tmp->mfcr2_dnis_index = 0;
@@ -11423,6 +11519,7 @@
 				ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
 				ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
 				ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
+				ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
 				ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
 				ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
 				ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
@@ -12674,6 +12771,8 @@
 				mfcr2_cur_get_ani_first = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
 				mfcr2_cur_double_answer = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
+				mfcr2_cur_accept_on_offer = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
 				mfcr2_cur_charge_calls = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {

Modified: team/moy/mfcr2-1.4/configs/chan_dahdi.conf.sample
URL: http://svn.digium.com/svn-view/asterisk/team/moy/mfcr2-1.4/configs/chan_dahdi.conf.sample?view=diff&rev=172068&r1=172067&r2=172068
==============================================================================
--- team/moy/mfcr2-1.4/configs/chan_dahdi.conf.sample (original)
+++ team/moy/mfcr2-1.4/configs/chan_dahdi.conf.sample Wed Jan 28 15:09:58 2009
@@ -770,6 +770,17 @@
 ; to the accepted state for incoming calls
 ; mfcr2_immediate_accept=no
 
+; You most likely dont need this feature. Default is yes.
+; When this is set to yes, all calls that are offered (incoming calls) which
+; DNIS is valid (exists in extensions.conf) and pass collect call validation 
+; will be accepted with a Group B tone (either call with charge or not, depending on mfcr2_charge_calls)
+; with this set to 'no' then the call will NOT be accepted on offered, and the call will start its
+; execution in extensions.conf without being accepted until the channel is answered (either with Answer() or
+; any other application resulting in the channel being answered). 
+; This is required to be 'no' if your telco needs the hangup cause to be set properly, or the PBX you 
+; are connecting Asterisk to relies on the hangup cause to be used for billing purposes
+; mfcr2_accept_on_offer=yes
+
 ; WARNING: advanced users only! I really mean it
 ; this parameter is commented by default because
 ; YOU DON'T NEED IT UNLESS YOU REALLY GROK MFC/R2




More information about the asterisk-commits mailing list