/* * Asterisk -- A telephony toolkit for Linux. * * This program is free software, distributed under the terms of * the GNU General Public License * app_intercept.c * Copyright Anthony C Minessale II * contributed by Edgewater Networks to the community. www.edgewaternetworks.com */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static char *tdesc = "Intercept an unaswered Call."; static char *app = "Intercept"; static char *synopsis = "Intercept([||auto])\n" "\n" "Intercept an unanswered channel:\n" " A) who's name begins with \n" " B) Containing the variable INTERCEPT_TAG matching \n" " C) The first encountered unanswered channel if 'auto' was specified.\n"; STANDARD_LOCAL_USER; LOCAL_USER_DECL; static struct ast_channel *ast_find_chan(struct ast_channel *me, char *match) { struct ast_channel *chan; chan = ast_channel_walk_locked(NULL); char *var; while (chan) { if ( (chan->_state != AST_STATE_UP && chan != me ) && (!strncasecmp(chan->name, match, strlen(match)) || (!strcasecmp(match,"auto")) || ((var = pbx_builtin_getvar_helper(chan,"INTERCEPT_TAG")) && !strcasecmp(var,match)))) return chan; ast_mutex_unlock(&chan->lock); chan = ast_channel_walk_locked(chan); } return NULL; } static int intercept_exec(struct ast_channel *chan, void *data) { int res=0; struct localuser *u; struct ast_channel *newchan; struct ast_channel *target_chan; struct ast_frame *f; struct ast_bridge_config config; char *chan_match; if (!data || ast_strlen_zero((char *) data)) { ast_log(LOG_WARNING, "Intercept requires an argument.\n"); return -1; } chan_match = ast_strdupa((char *) data); if ((target_chan = ast_find_chan(chan, chan_match))) { ast_mutex_unlock(&target_chan->lock); } else { ast_log(LOG_WARNING, "No Channels To intercept.\n"); return -1; } LOCAL_USER_ADD(u); newchan = ast_channel_alloc(0); snprintf(newchan->name, sizeof (newchan->name), "Intercept/%s",target_chan->name); newchan->readformat = target_chan->readformat; newchan->writeformat = target_chan->writeformat; ast_channel_masquerade(newchan, target_chan); if ((f = ast_read(newchan))) { ast_frfree(f); memset(&config,0,sizeof(struct ast_bridge_config)); config.allowredirect_in = 1; config.allowredirect_out = 1; config.allowdisconnect_in = 1; config.allowdisconnect_out = 1; if (newchan->_state != AST_STATE_UP) ast_answer(newchan); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "%s Drops Back to Pass, Picked Off by %s! ... The 10 ... the 5 ... Touchdown!!!\n", newchan->name, chan->name); chan->appl = "Bridged Call"; res = ast_bridge_call(chan,newchan,&config); } ast_hangup(newchan); LOCAL_USER_REMOVE(u); return res ? 0 : -1; } int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; return ast_unregister_application(app); } int load_module(void) { return ast_register_application(app, intercept_exec, tdesc, synopsis); } char *description(void) { return tdesc; } int usecount(void) { int res; STANDARD_USECOUNT(res); return res; } char *key() { return ASTERISK_GPL_KEY; }