[asterisk-commits] russell: branch 1.4 r66881 - /branches/1.4/channels/chan_skinny.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Jun 1 12:41:31 MST 2007


Author: russell
Date: Fri Jun  1 14:41:30 2007
New Revision: 66881

URL: http://svn.digium.com/view/asterisk?view=rev&rev=66881
Log:
Changes to the way DTMF is handled in the core broke dialing in chan_skinny.
This patch makes chan_skinny usable again.  I did not end up testing this,
but there are multiple positive test reports listed in the bug report.
(issue #9596, reported by pj, testing by pj and mvanbaak, and the fix was
 written by DEA)

Modified:
    branches/1.4/channels/chan_skinny.c

Modified: branches/1.4/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/chan_skinny.c?view=diff&rev=66881&r1=66880&r2=66881
==============================================================================
--- branches/1.4/channels/chan_skinny.c (original)
+++ branches/1.4/channels/chan_skinny.c Fri Jun  1 14:41:30 2007
@@ -998,6 +998,7 @@
 	int lastlineinstance;
 	int lastcallreference;
 	int capability;
+	char exten[AST_MAX_EXTENSION];
 	struct sockaddr_in addr;
 	struct in_addr ourip;
 	struct skinny_line *lines;
@@ -1189,6 +1190,9 @@
 {
 	struct skinny_line *l;
 
+	if (!instance)
+		instance = 1;
+
 	for (l = d->lines; l; l = l->next) {
 		if (l->instance == instance)
 			break;
@@ -1246,9 +1250,13 @@
 		return NULL;
 	}
 
-	for (sub = l->sub; sub; sub = sub->next) {
-		if (sub->callid == reference)
-			break;
+	if (!reference)
+		sub = l->sub;
+	else {
+		for (sub = l->sub; sub; sub = sub->next) {
+			if (sub->callid == reference)
+				break;
+		}
 	}
 
 	if (!sub) {
@@ -2270,36 +2278,39 @@
 	struct skinny_line *l = sub->parent;
 	struct skinny_device *d = l->parent;
 	struct skinnysession *s = d->session;
-	char exten[AST_MAX_EXTENSION] = "";
 	int len = 0;
 	int timeout = firstdigittimeout;
-	int res;
+	int res = 0;
 	int getforward=0;
+	int loop_pause = 100;
 
 	if (option_verbose > 2)
 		ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, d->name);
+	len = strlen(d->exten);
 
 	while (len < AST_MAX_EXTENSION-1) {
-		res = ast_waitfordigit(c, timeout);
-		timeout = 0;
-		if (res < 0) {
-			if (skinnydebug)
-				ast_verbose("Skinny(%s@%s): waitfordigit returned < 0\n", l->name, d->name);
-			ast_indicate(c, -1);
-			ast_hangup(c);
-			return NULL;
-		} else if (res) {
-			exten[len++]=res;
-			exten[len] = '\0';
-		}
-		if (!ast_ignore_pattern(c->context, exten)) {
+
+		res = 1;  /* Assume we will get a digit */
+		while (strlen(d->exten) == len) {
+			ast_safe_sleep(c, loop_pause);
+			timeout -= loop_pause;
+			if (timeout <= 0){
+				res = 0;
+				break;
+			}
+		}
+
+		len = strlen(d->exten);
+
+		if (len && !ast_ignore_pattern(c->context, d->exten)) {
 			transmit_tone(s, SKINNY_SILENCE);
 		}
-		if (ast_exists_extension(c, c->context, exten, 1, l->cid_num)) {
-			if (!res || !ast_matchmore_extension(c, c->context, exten, 1, l->cid_num)) {
+
+		if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
+			if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
 				if (getforward) {
 					/* Record this as the forwarding extension */
-					ast_copy_string(l->call_forward, exten, sizeof(l->call_forward));
+					ast_copy_string(l->call_forward, d->exten, sizeof(l->call_forward));
 					if (option_verbose > 2)
 						ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
 							l->call_forward, c->name);
@@ -2310,13 +2321,14 @@
 					ast_safe_sleep(c, 500);
 					ast_indicate(c, -1);
  					ast_safe_sleep(c, 1000);
-					memset(exten, 0, sizeof(exten));
+					memset(d->exten, 0, sizeof(d->exten));
 					transmit_tone(s, SKINNY_DIALTONE);
 					len = 0;
 					getforward = 0;
 				} else {
-					ast_copy_string(c->exten, exten, sizeof(c->exten));
-					ast_copy_string(l->lastnumberdialed, exten, sizeof(l->lastnumberdialed));
+					ast_copy_string(c->exten, d->exten, sizeof(c->exten));
+					ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
+					memset (d->exten, 0, sizeof(d->exten));
 					skinny_newcall(c);
 					return NULL;
 				}
@@ -2328,11 +2340,14 @@
 		} else if (res == 0) {
 			ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
 			transmit_tone(s, SKINNY_REORDER);
-			ast_hangup(c);
+			if (sub->owner && sub->owner->_state != AST_STATE_UP) {
+				ast_indicate(c, -1);
+				ast_hangup(c);
+			}
 			return NULL;
-		} else if (!ast_canmatch_extension(c, c->context, exten, 1, c->cid.cid_num) &&
-			   ((exten[0] != '*') || (!ast_strlen_zero(exten) > 2))) {
-			ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
+		} else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
+			   ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
+			ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
 			transmit_tone(s, SKINNY_REORDER);
 			/* hang out for 3 seconds to let congestion play */
 			ast_safe_sleep(c, 3000);
@@ -2341,11 +2356,13 @@
 		if (!timeout) {
 			timeout = gendigittimeout;
 		}
-		if (len && !ast_ignore_pattern(c->context, exten)) {
+		if (len && !ast_ignore_pattern(c->context, d->exten)) {
 			ast_indicate(c, -1);
 		}
 	}
-	ast_hangup(c);
+	if (c)
+		ast_hangup(c);
+
 	return NULL;
 }
 
@@ -4001,6 +4018,10 @@
 static int handle_message(struct skinny_req *req, struct skinnysession *s)
 {
 	int res = 0;
+	struct skinny_device *d = s->device;
+	struct skinny_subchannel *sub;
+	int lineInstance;
+	int callReference;
 
 	if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
 		ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
@@ -4025,7 +4046,43 @@
 		if (skinnydebug)
 			ast_verbose("Collected digit: [%d]\n", letohl(req->data.keypad.button));
 
-		res = handle_keypad_button_message(req, s);
+		lineInstance = letohl(req->data.keypad.lineInstance);
+		callReference = letohl(req->data.keypad.callReference);
+
+		sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
+
+		if (sub && (sub->owner->_state <  AST_STATE_UP)) {
+			char dgt;
+			int digit = letohl(req->data.keypad.button);
+			size_t len;
+
+			if (digit == 14) {
+				dgt = '*';
+			} else if (digit == 15) {
+				dgt = '#';
+			} else if (digit >= 0 && digit <= 9) {
+				dgt = '0' + digit;
+			} else {
+				/* digit=10-13 (A,B,C,D ?), or
+		 		* digit is bad value
+		 		*
+		 		* probably should not end up here, but set
+		 		* value for backward compatibility, and log
+		 		* a warning.
+		 		*/
+				dgt = '0' + digit;
+				ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
+			}
+
+			len = strlen(d->exten);
+			if (len < sizeof(d->exten) - 1) {
+				d->exten[len] = dgt;
+				d->exten[len] = '\0';
+			} else {
+				ast_log(LOG_WARNING, "Dropping digit with value %d because digit queue is full\n", dgt);
+			}
+		} else
+			res = handle_keypad_button_message(req, s);
 		break;
 	case STIMULUS_MESSAGE:
 		res = handle_stimulus_message(req, s);



More information about the asterisk-commits mailing list