aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_skinny.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-06-01 19:41:30 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-06-01 19:41:30 +0000
commitcf785efa8ba6945030675abc016f9d559feacc7d (patch)
treeec9fa35d0cb109d5ee00aa3b3a3e88d3ef29f8e9 /channels/chan_skinny.c
parent36bcb70b8ca997e10c705dd9f2d050d65233d4db (diff)
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) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@66881 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_skinny.c')
-rw-r--r--channels/chan_skinny.c117
1 files changed, 87 insertions, 30 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index c1ecfa6a8..1a4c10d54 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -998,6 +998,7 @@ static struct skinny_device {
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 @@ static struct skinny_line *find_line_by_instance(struct skinny_device *d, int in
{
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 @@ static struct skinny_subchannel *find_subchannel_by_instance_reference(struct sk
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 @@ static void *skinny_ss(void *data)
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';
+
+ 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;
+ }
}
- if (!ast_ignore_pattern(c->context, exten)) {
+
+ 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 @@ static void *skinny_ss(void *data)
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 @@ static void *skinny_ss(void *data)
} 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 @@ static void *skinny_ss(void *data)
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_register_available_lines_message(struct skinny_req *req, struc
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 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s)
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);