diff options
Diffstat (limited to 'apps/app_dial.c')
-rwxr-xr-x | apps/app_dial.c | 243 |
1 files changed, 122 insertions, 121 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index 722b0795e..abfb2dd37 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -175,6 +175,8 @@ static void *do_parking_thread(void *ignore) pu = pu->next; free(pt); } else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) { + if (FD_ISSET(pu->chan->fd, &efds)) + pu->chan->exception = 1; /* See if they need servicing */ f = ast_read(pu->chan); if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) { @@ -306,6 +308,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu if (o->stillgoing) { o->chan->blocking = 0; if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) { + if (FD_ISSET(o->chan->fd, &efds)) + o->chan->exception = 1; f = ast_read(o->chan); if (f) { if (f->frametype == AST_FRAME_CONTROL) { @@ -347,6 +351,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu } if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) { /* After unblocking the entirity of the list, check for the main channel */ + if (FD_ISSET(in->fd, &efds)) + in->exception = 1; f = ast_read(in); #if 0 if (f && (f->frametype != AST_FRAME_VOICE)) @@ -370,8 +376,7 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a { /* Copy voice back and forth between the two channels. Give the peer the ability to transfer calls with '#<extension' syntax. */ - struct ast_channel *cs[3]; - int to = -1, len; + int len; struct ast_frame *f; struct ast_channel *who; char newext[256], *ptr; @@ -382,98 +387,79 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a return -1; peer->appl = "Bridged Call"; peer->data = chan->name; - cs[0] = chan; - cs[1] = peer; - for (/* ever */;;) { - who = ast_waitfor_n(cs, 2, &to); - if (!who) { - ast_log(LOG_WARNING, "Nobody there??\n"); - continue; - } - f = ast_read(who); - if (!f || ((f->frametype == AST_FRAME_CONTROL) && - ((f->subclass == AST_CONTROL_HANGUP) || - (f->subclass == AST_CONTROL_BUSY)))) + for (;;) { + res = ast_channel_bridge(chan, peer, AST_BRIDGE_DTMF_CHANNEL_1, &f, &who); + if (res < 0) { + ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); return -1; - if ((f->frametype == AST_FRAME_VOICE) || - (f->frametype == AST_FRAME_DTMF) || - (f->frametype == AST_FRAME_TEXT)) { - if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect && - (f->subclass == '#')) { - if (f->subclass == '#') { - memset(newext, 0, sizeof(newext)); - ptr = newext; - len = ast_pbx_longest_extension(chan->context) + 1; - if (len < ast_pbx_longest_extension("default") + 1) - len = ast_pbx_longest_extension("default") + 1; - + } + + if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || + (f->subclass == AST_CONTROL_CONGESTION)))) { + res = -1; + break; + } + if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect && + (f->subclass == '#')) { + memset(newext, 0, sizeof(newext)); + ptr = newext; + len = ast_pbx_longest_extension(chan->context) + 1; + if (len < ast_pbx_longest_extension("default") + 1) + len = ast_pbx_longest_extension("default") + 1; /* Transfer */ - if ((res=ast_streamfile(peer, "pbx-transfer", chan->language))) - break; - if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0) - break; - ast_stopstream(peer); - if (res > 0) { - /* If they've typed a digit already, handle it */ - newext[0] = res; - ptr++; - len --; - } - res = ast_readstring(peer, ptr, len, 3000, 2000, "#"); - if (res) - break; - if (!strcmp(newext, parking_ext)) { - if (!park_call(chan, peer)) { - /* We return non-zero, but tell the PBX not to hang the channel when - the thread dies -- We have to be careful now though. We are responsible for - hanging up the channel, else it will never be hung up! */ - res=AST_PBX_KEEPALIVE; - break; - } else { - ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name); - } - /* XXX Maybe we should have another message here instead of invalid extension XXX */ - } else if (ast_exists_extension(chan, peer->context, newext, 1)) { - /* Set the channel's new extension, since it exists, using peer context */ - strncpy(chan->exten, newext, sizeof(chan->exten)); - strncpy(chan->context, peer->context, sizeof(chan->context)); - chan->priority = 0; - ast_frfree(f); - res=0; - break; - } else if (ast_exists_extension(chan, "default", newext, 1)) { - /* Set the channel's new extension, since it exists, using peer context */ - strncpy(chan->exten, newext, sizeof(chan->exten)); - strncpy(chan->context, "default", sizeof(chan->context)); - chan->priority = 0; - ast_frfree(f); - res=0; + if ((res=ast_streamfile(peer, "pbx-transfer", chan->language))) + break; + if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0) + break; + ast_stopstream(peer); + if (res > 0) { + /* If they've typed a digit already, handle it */ + newext[0] = res; + ptr++; + len --; + } + res = ast_readstring(peer, ptr, len, 3000, 2000, "#"); + if (res) + break; + if (!strcmp(newext, parking_ext)) { + if (!park_call(chan, peer)) { + /* We return non-zero, but tell the PBX not to hang the channel when + the thread dies -- We have to be careful now though. We are responsible for + hanging up the channel, else it will never be hung up! */ + res=AST_PBX_KEEPALIVE; break; + } else { + ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name); } - res = ast_streamfile(peer, "pbx-invalid", chan->language); - if (res) - break; - res = ast_waitstream(peer, AST_DIGIT_ANY); - ast_stopstream(peer); - res = 0; + /* XXX Maybe we should have another message here instead of invalid extension XXX */ + } else if (ast_exists_extension(chan, peer->context, newext, 1)) { + /* Set the channel's new extension, since it exists, using peer context */ + strncpy(chan->exten, newext, sizeof(chan->exten)); + strncpy(chan->context, peer->context, sizeof(chan->context)); + chan->priority = 0; + ast_frfree(f); + res=0; + break; + } else if (ast_exists_extension(chan, "default", newext, 1)) { + /* Set the channel's new extension, since it exists, using peer context */ + strncpy(chan->exten, newext, sizeof(chan->exten)); + strncpy(chan->context, "default", sizeof(chan->context)); + chan->priority = 0; + ast_frfree(f); + res=0; + break; } + res = ast_streamfile(peer, "pbx-invalid", chan->language); + if (res) + break; + res = ast_waitstream(peer, AST_DIGIT_ANY); + ast_stopstream(peer); + res = 0; } else { -#if 0 - ast_log(LOG_DEBUG, "Read from %s\n", who->name); +#if 1 + ast_log(LOG_DEBUG, "Read from %s (%d,%d)\n", who->name, f->frametype, f->subclass); #endif - if (who == chan) - ast_write(peer, f); - else - ast_write(chan, f); } - ast_frfree(f); - - } else - ast_frfree(f); - /* Swap who gets priority */ - cs[2] = cs[0]; - cs[0] = cs[1]; - cs[1] = cs[2]; } return res; } @@ -482,7 +468,7 @@ static int park_exec(struct ast_channel *chan, void *data) { int res=0; struct localuser *u; - struct ast_channel *peer=NULL, *nchan; + struct ast_channel *peer=NULL; struct parkeduser *pu, *pl=NULL; int park; if (!data) { @@ -509,13 +495,9 @@ static int park_exec(struct ast_channel *chan, void *data) free(pu); } if (peer) { - /* Build a translator if necessary */ - if (peer->format & chan->format) - nchan = chan; - else - nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH); - if (!nchan) { - ast_log(LOG_WARNING, "Had to drop call because there was no translator for %s to %s.\n", chan->name, peer->name); + res = ast_channel_make_compatible(chan, peer); + if (res < 0) { + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name); ast_hangup(peer); return -1; } @@ -523,9 +505,7 @@ static int park_exec(struct ast_channel *chan, void *data) were the person called. */ if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park); - res = bridge_call(peer, nchan, 1); - if (nchan != chan) - ast_translator_destroy(nchan); + res = bridge_call(peer, chan, 1); /* Simulate the PBX hanging up */ if (res != AST_PBX_KEEPALIVE) ast_hangup(peer); @@ -546,7 +526,7 @@ static int dial_exec(struct ast_channel *chan, void *data) struct localuser *u; char *info, *peers, *timeout, *tech, *number, *rest, *cur; struct localuser *outgoing=NULL, *tmp; - struct ast_channel *peer, *npeer; + struct ast_channel *peer; int to; int allowredir=0; char numsubst[AST_MAX_EXTENSION]; @@ -562,25 +542,42 @@ static int dial_exec(struct ast_channel *chan, void *data) /* Parse our arguments XXX Check for failure XXX */ info = malloc(strlen((char *)data) + AST_MAX_EXTENSION); + if (!info) { + ast_log(LOG_WARNING, "Out of memory\n"); + return -1; + } strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION); - peers = strtok(info, "|"); - if (!peers) { + peers = info; + if (peers) { + timeout = strchr(info, '|'); + if (timeout) { + *timeout = '\0'; + timeout++; + } + } else + timeout = NULL; + if (!peers || !strlen(peers)) { ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n"); goto out; } - timeout = strtok(NULL, "|"); - rest = peers; + + cur = peers; do { - cur = strtok(rest, "&"); /* Remember where to start next time */ - rest = strtok(NULL, "\128"); + rest = strchr(cur, '&'); + if (rest) { + *rest = 0; + rest++; + } /* Get a technology/[device:]number pair */ - tech = strtok(cur, "/"); - number = strtok(NULL, "&"); + tech = cur; + number = strchr(tech, '/'); if (!number) { ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n"); goto out; } + *number = '\0'; + number++; tmp = malloc(sizeof(struct localuser)); if (!tmp) { ast_log(LOG_WARNING, "Out of memory\n"); @@ -598,15 +595,18 @@ static int dial_exec(struct ast_channel *chan, void *data) ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst); } /* Request the peer */ - tmp->chan = ast_request(tech, chan->format, numsubst); + tmp->chan = ast_request(tech, chan->nativeformats, numsubst); if (!tmp->chan) { /* If we can't, just go on to the next call */ ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech); free(tmp); + cur = rest; continue; } tmp->chan->appl = "AppDial"; tmp->chan->data = "(Outgoing Line)"; + if (chan->callerid) + tmp->chan->callerid = strdup(chan->callerid); /* Place the call, but don't wait on the answer */ res = ast_call(tmp->chan, numsubst, 0); if (res) { @@ -627,7 +627,9 @@ static int dial_exec(struct ast_channel *chan, void *data) tmp->stillgoing = -1; tmp->next = outgoing; outgoing = tmp; - } while(rest); + cur = rest; + } while(cur); + if (timeout) to = atoi(timeout) * 1000; else @@ -649,21 +651,15 @@ static int dial_exec(struct ast_channel *chan, void *data) conversation. */ hanguptree(outgoing, peer); outgoing = NULL; - /* Build a translator if necessary */ - if (peer->format & chan->format) - npeer = peer; - else - npeer = ast_translator_create(peer, chan->format, AST_DIRECTION_BOTH); - if (!npeer) { - ast_log(LOG_WARNING, "Had to drop call because there was no translator for %s to %s.\n", chan->name, peer->name); - ast_hangup(peer); - res = -1; - } else { - res = bridge_call(chan, npeer, allowredir); - if (npeer != peer) - ast_translator_destroy(npeer); + /* Make sure channels are compatible */ + res = ast_channel_make_compatible(chan, peer); + if (res < 0) { + ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name); ast_hangup(peer); + return -1; } + res = bridge_call(chan, peer, allowredir); + ast_hangup(peer); } out: hanguptree(outgoing, NULL); @@ -711,3 +707,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} |