|
|
|
@ -506,18 +506,24 @@ static struct ast_generator spygen = {
|
|
|
|
|
|
|
|
|
|
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook, struct ast_flags *flags)
|
|
|
|
|
{
|
|
|
|
|
int res;
|
|
|
|
|
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
|
|
|
|
|
if(ast_test_flag(flags, OPTION_READONLY)) {
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(flags, OPTION_READONLY)) {
|
|
|
|
|
ast_set_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE);
|
|
|
|
|
} else {
|
|
|
|
|
ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
|
|
|
|
|
}
|
|
|
|
|
if(ast_test_flag(flags, OPTION_LONG_QUEUE)) {
|
|
|
|
|
if (ast_test_flag(flags, OPTION_LONG_QUEUE)) {
|
|
|
|
|
ast_debug(9, "Using a long queue to store audio frames in spy audiohook\n");
|
|
|
|
|
} else {
|
|
|
|
|
ast_set_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE);
|
|
|
|
|
}
|
|
|
|
|
return ast_audiohook_attach(autochan->chan, audiohook);
|
|
|
|
|
res = ast_audiohook_attach(autochan->chan, audiohook);
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void change_spy_mode(const char digit, struct ast_flags *flags)
|
|
|
|
@ -601,8 +607,14 @@ static int attach_barge(struct ast_autochan *spyee_autochan,
|
|
|
|
|
{
|
|
|
|
|
int retval = 0;
|
|
|
|
|
struct ast_autochan *internal_bridge_autochan;
|
|
|
|
|
RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(spyee_autochan->chan), ast_channel_cleanup);
|
|
|
|
|
struct ast_channel *spyee_chan;
|
|
|
|
|
RAII_VAR(struct ast_channel *, bridged, NULL, ast_channel_cleanup);
|
|
|
|
|
|
|
|
|
|
ast_autochan_channel_lock(spyee_autochan);
|
|
|
|
|
spyee_chan = ast_channel_ref(spyee_autochan->chan);
|
|
|
|
|
ast_autochan_channel_unlock(spyee_autochan);
|
|
|
|
|
bridged = ast_channel_bridge_peer(spyee_chan);
|
|
|
|
|
ast_channel_unref(spyee_chan);
|
|
|
|
|
if (!bridged) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@ -614,12 +626,10 @@ static int attach_barge(struct ast_autochan *spyee_autochan,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_autochan_channel_lock(internal_bridge_autochan);
|
|
|
|
|
if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook, flags)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name);
|
|
|
|
|
retval = -1;
|
|
|
|
|
}
|
|
|
|
|
ast_autochan_channel_unlock(internal_bridge_autochan);
|
|
|
|
|
|
|
|
|
|
*spyee_bridge_autochan = internal_bridge_autochan;
|
|
|
|
|
|
|
|
|
@ -639,21 +649,25 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
|
|
|
|
|
struct ast_autochan *spyee_bridge_autochan = NULL;
|
|
|
|
|
const char *spyer_name;
|
|
|
|
|
|
|
|
|
|
if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan) ||
|
|
|
|
|
ast_test_flag(ast_channel_flags(spyee_autochan->chan), AST_FLAG_ZOMBIE)) {
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
if (ast_check_hangup(chan)) {
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
spyer_name = ast_strdupa(ast_channel_name(chan));
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
|
|
ast_autochan_channel_lock(spyee_autochan);
|
|
|
|
|
if (ast_check_hangup(spyee_autochan->chan)
|
|
|
|
|
|| ast_test_flag(ast_channel_flags(spyee_autochan->chan), AST_FLAG_ZOMBIE)) {
|
|
|
|
|
ast_autochan_channel_unlock(spyee_autochan);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
name = ast_strdupa(ast_channel_name(spyee_autochan->chan));
|
|
|
|
|
ast_autochan_channel_unlock(spyee_autochan);
|
|
|
|
|
|
|
|
|
|
ast_verb(2, "Spying on channel %s\n", name);
|
|
|
|
|
publish_chanspy_message(chan, spyee_autochan->chan, 1);
|
|
|
|
|
ast_autochan_channel_unlock(spyee_autochan);
|
|
|
|
|
|
|
|
|
|
memset(&csth, 0, sizeof(csth));
|
|
|
|
|
ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);
|
|
|
|
@ -845,7 +859,7 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
|
|
|
|
|
struct ast_autochan *autochan, struct ast_channel *chan)
|
|
|
|
|
struct ast_channel *chan)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel *next;
|
|
|
|
|
struct ast_autochan *autochan_store;
|
|
|
|
@ -982,11 +996,12 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
waitms = 100;
|
|
|
|
|
num_spyed_upon = 0;
|
|
|
|
|
|
|
|
|
|
for (autochan = next_channel(iter, autochan, chan);
|
|
|
|
|
autochan;
|
|
|
|
|
prev = autochan->chan, ast_autochan_destroy(autochan),
|
|
|
|
|
autochan = next_autochan ? next_autochan :
|
|
|
|
|
next_channel(iter, autochan, chan), next_autochan = NULL) {
|
|
|
|
|
for (autochan = next_channel(iter, chan);
|
|
|
|
|
autochan;
|
|
|
|
|
prev = autochan->chan,
|
|
|
|
|
ast_autochan_destroy(autochan),
|
|
|
|
|
autochan = next_autochan ?: next_channel(iter, chan),
|
|
|
|
|
next_autochan = NULL) {
|
|
|
|
|
int igrp = !mygroup;
|
|
|
|
|
int ienf = !myenforced;
|
|
|
|
|
|
|
|
|
@ -1000,13 +1015,19 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_channel_is_bridged(autochan->chan)) {
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
if (ast_test_flag(flags, OPTION_BRIDGED)
|
|
|
|
|
&& !ast_channel_is_bridged(autochan->chan)) {
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ast_check_hangup(autochan->chan) || ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
|
|
|
|
|
if (ast_check_hangup(autochan->chan)
|
|
|
|
|
|| ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
|
|
|
|
|
if (mygroup) {
|
|
|
|
|
int num_groups = 0;
|
|
|
|
@ -1024,11 +1045,13 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
|
|
|
|
|
/* Before dahdi scan was part of chanspy, it would use the "GROUP" variable
|
|
|
|
|
* rather than "SPYGROUP", this check is done to preserve expected behavior */
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
|
|
|
|
|
group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
|
|
|
|
|
} else {
|
|
|
|
|
group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
|
|
|
|
|
}
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
|
|
|
|
|
if (!ast_strlen_zero(group)) {
|
|
|
|
|
ast_copy_string(dup_group, group, sizeof(dup_group));
|
|
|
|
@ -1056,7 +1079,9 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
|
|
|
|
|
snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
|
|
|
|
|
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
ast_copy_string(ext + 1, ast_channel_name(autochan->chan), sizeof(ext) - 1);
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
if ((end = strchr(ext, '-'))) {
|
|
|
|
|
*end++ = ':';
|
|
|
|
|
*end = '\0';
|
|
|
|
@ -1078,7 +1103,9 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
char *ptr, *s;
|
|
|
|
|
|
|
|
|
|
strcpy(peer_name, "spy-");
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
if ((ptr = strchr(peer_name, '/'))) {
|
|
|
|
|
*ptr++ = '\0';
|
|
|
|
|
for (s = peer_name; s < ptr; s++) {
|
|
|
|
@ -1143,12 +1170,14 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
|
|
|
|
next = ast_channel_unref(next);
|
|
|
|
|
} else {
|
|
|
|
|
/* stay on this channel, if it is still valid */
|
|
|
|
|
ast_autochan_channel_lock(autochan);
|
|
|
|
|
if (!ast_check_hangup(autochan->chan)) {
|
|
|
|
|
next_autochan = ast_autochan_setup(autochan->chan);
|
|
|
|
|
} else {
|
|
|
|
|
/* the channel is gone */
|
|
|
|
|
next_autochan = NULL;
|
|
|
|
|
}
|
|
|
|
|
ast_autochan_channel_unlock(autochan);
|
|
|
|
|
}
|
|
|
|
|
} else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
|
|
|
|
|
ast_autochan_destroy(autochan);
|
|
|
|
|