/* * app_intercept.c -- A Module To Intercept a Ringing Call * * Copyright (c) 2004-2007 Anthony Minessale II * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #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" " e.g. Intercept(SIP/1000)\n" " B) Containing the variable INTERCEPT_TAG matching \n" " e.g. Intercept(GROUP1) will match calls that Set(INTERCEPT_TAG=GROUP1)\n" " C) The first encountered unanswered channel if 'auto' was specified.\n" " e.g. Intercept(auto)\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; int state; while (chan) { if ((var = pbx_builtin_getvar_helper(chan,"INTERCEPT_TAG")) && !strcasecmp(var, match)) { return chan; } else if ( (chan->_state == AST_STATE_RING && chan != me ) && (!strncasecmp(chan->name, match, strlen(match)) || (!strcasecmp(match, "auto")))) { return chan; } else if ( (chan->_state == AST_STATE_RINGING && chan != me ) && (!strncasecmp(chan->name, match, strlen(match)) || (!strcasecmp(match, "auto")))) { 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; newchan->_state = AST_STATE_UP; ast_clear_flag(newchan, AST_FLAGS_ALL); newchan->_softhangup = 0; ast_channel_masquerade(newchan, target_chan); if ((f = ast_read(newchan))) { ast_frfree(f); memset(&config,0,sizeof(struct ast_bridge_config)); 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); if(!(res = ast_channel_make_compatible(chan, newchan))) { chan->appl = "Bridged Call"; res = ast_bridge_call(chan,newchan,&config); } else { ast_verbose("DoH! cant make chans compat.\n"); } } 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; }