minor tweak and optimization for chanspy

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5317 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Anthony Minessale II 20 years ago
parent 318406a0c5
commit e03ed12e00

@ -31,13 +31,11 @@
AST_MUTEX_DEFINE_STATIC(modlock);
#define ast_fit_in_short(in) (in < -32768 ? -32768 : in > 32767 ? 32767 : in)
#define find_smallest_of_three(a, b, c) ((a < b && a < c) ? a : (b < a && b < c) ? b : c)
#define AST_NAME_STRLEN 256
#define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
#define minmax(x,y) x ? (x > y) ? y : ((x < (y * -1)) ? (y * -1) : x) : 0
#define CS_BUFLEN 640
#define CS_BUFLEN 1024
static char *synopsis = "Tap into any type of asterisk channel and listen to audio";
static char *app = "ChanSpy";
@ -69,14 +67,28 @@ AST_DECLARE_OPTIONS(chanspy_opts,{
});
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct chanspy_translation_helper {
/* spy data */
struct ast_channel_spy spy;
/* read frame */
int fmt0;
short buf0[CS_BUFLEN];
struct ast_trans_pvt *trans0;
/* write frame */
int fmt1;
struct ast_trans_pvt *trans1;
short buf1[CS_BUFLEN];
/* muxed frame */
struct ast_frame frame;
short buf[CS_BUFLEN];
int volfactor;
struct ast_channel_spy *spy;
};
/* Prototypes */
@ -192,95 +204,122 @@ static void ast_flush_spy_queue(struct ast_channel_spy *spy)
static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame *f0, *f1, write_frame, *f;
int x=0, framelen_a = 0, framelen_b = 0, size = 0;
short buf[CS_BUFLEN], buf0[CS_BUFLEN], buf1[CS_BUFLEN];
struct ast_frame *f, *f0, *f1;
int x = 0, vf = 0;
struct chanspy_translation_helper *csth = data;
int nc = 0, vf;
ast_mutex_lock(&csth->spy.lock);
f0 = spy_queue_shift(&csth->spy, 0);
f1 = spy_queue_shift(&csth->spy, 1);
ast_mutex_unlock(&csth->spy.lock);
ast_mutex_lock(&csth->spy->lock);
f0 = spy_queue_shift(csth->spy, 0);
f1 = spy_queue_shift(csth->spy, 1);
ast_mutex_unlock(&csth->spy->lock);
if (f0 && f1) {
if (!csth->trans0) {
if (f0->subclass != AST_FORMAT_SLINEAR && (csth->trans0 = ast_translator_build_path(AST_FORMAT_SLINEAR, f0->subclass)) == NULL) {
ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f0->subclass));
return -1;
}
if (!csth->trans1) {
if (f1->subclass == f0->subclass) {
csth->trans1 = csth->trans0;
} else if (f1->subclass != AST_FORMAT_SLINEAR && (csth->trans1 = ast_translator_build_path(AST_FORMAT_SLINEAR, f1->subclass)) == NULL) {
ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f1->subclass));
return -1;
}
}
}
if (!f0 && !f1) {
return 0;
}
if (f0 && csth->fmt0 && csth->fmt0 != f0->subclass) {
ast_translator_free_path(csth->trans0);
csth->trans0 = NULL;
csth->fmt0 = csth->fmt0;
}
if (f1 && csth->fmt1 && csth->fmt1 != f1->subclass) {
ast_translator_free_path(csth->trans1);
csth->trans1 = NULL;
csth->fmt1 = csth->fmt1;
}
if (!csth->fmt0 && f0) {
csth->fmt0 = f0->subclass;
}
memset(buf, 0, sizeof(buf));
memset(buf0, 0, sizeof(buf0));
memset(buf1, 0, sizeof(buf1));
if (!csth->fmt1 && f1) {
csth->fmt1 = f1->subclass;
}
if (csth->fmt0 && csth->fmt0 != AST_FORMAT_SLINEAR && !csth->trans0) {
if (csth->fmt0 == csth->fmt1 && csth->trans1) {
csth->trans0 = csth->trans1;
} else if ((csth->trans0 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt0)) == NULL) {
ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt0));
return -1;
}
}
if (csth->fmt1 && csth->fmt1 != AST_FORMAT_SLINEAR && !csth->trans1) {
if (csth->fmt1 == csth->fmt0 && csth->trans0) {
csth->trans1 = csth->trans0;
} else if ((csth->trans1 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt1)) == NULL) {
ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt1));
return -1;
}
}
if (f0) {
if (csth->trans0) {
if ((f = ast_translate(csth->trans0, f0, 0))) {
framelen_a = f->datalen * sizeof(short);
memcpy(buf0, f->data, framelen_a);
memcpy(csth->buf0, f->data, f->datalen * sizeof(short));
ast_frfree(f);
} else
} else {
return 0;
}
} else {
framelen_a = f0->datalen * sizeof(short);
memcpy(buf0, f0->data, framelen_a);
memcpy(csth->buf0, f0->data, f0->datalen * sizeof(short));
}
}
if (f1) {
if (csth->trans1) {
if ((f = ast_translate(csth->trans1, f1, 0))) {
framelen_b = f->datalen * sizeof(short);
memcpy(buf1, f->data, framelen_b);
memcpy(csth->buf1, f->data, f->datalen * sizeof(short));
ast_frfree(f);
} else
} else {
return 0;
}
} else {
framelen_b = f1->datalen * sizeof(short);
memcpy(buf1, f1->data, framelen_b);
memcpy(csth->buf1, f1->data, f1->datalen * sizeof(short));
}
size = find_smallest_of_three(len, framelen_a, framelen_b);
vf = get_volfactor(csth->volfactor);
vf = minmax(vf, 16);
for(x=0; x < size; x++) {
if (vf < 0) {
buf0[x] /= abs(vf);
buf1[x] /= abs(vf);
} else if (vf > 0) {
buf0[x] *= vf;
buf1[x] *= vf;
}
vf = get_volfactor(csth->volfactor);
vf = minmax(vf, 16);
for(x=0; x < len; x++) {
if (vf < 0) {
if (f0) {
csth->buf0[x] /= abs(vf);
}
if (f1) {
csth->buf1[x] /= abs(vf);
}
} else if (vf > 0) {
if (f0) {
csth->buf0[x] *= vf;
}
if (f1) {
csth->buf1[x] *= vf;
}
buf[x] = ast_fit_in_short(buf0[x] + buf1[x]);
}
memset(&write_frame, 0, sizeof(write_frame));
write_frame.frametype = AST_FRAME_VOICE;
write_frame.subclass = AST_FORMAT_SLINEAR;
write_frame.datalen = size;
write_frame.samples = size;
write_frame.data = buf;
write_frame.offset = 0;
ast_write(chan, &write_frame);
} else {
nc++;
if(nc > 1) {
return -1;
if (f0 && f1) {
csth->buf[x] = ast_fit_in_short(csth->buf0[x] + csth->buf1[x]);
} else if (f0) {
csth->buf[x] = csth->buf0[x];
} else if (f1) {
csth->buf[x] = csth->buf1[x];
}
}
csth->frame.data = csth->buf;
ast_write(chan, &csth->frame);
if (f0)
if (f0) {
ast_frfree(f0);
if (f1)
}
if (f1) {
ast_frfree(f1);
}
return 0;
}
static struct ast_generator spygen = {
@ -356,25 +395,25 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
int running = 1, res = 0, x = 0;
char inp[24];
char *name=NULL;
struct ast_channel_spy spy;
if (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee)) {
memset(inp, 0, sizeof(inp));
name = ast_strdupa(spyee->name);
if (option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
memset(&spy, 0, sizeof(struct ast_channel_spy));
spy.status = CHANSPY_RUNNING;
ast_mutex_init(&spy.lock);
start_spying(spyee, chan, &spy);
memset(&csth, 0, sizeof(csth));
csth.spy.status = CHANSPY_RUNNING;
ast_mutex_init(&csth.spy.lock);
csth.volfactor = *volfactor;
csth.spy = &spy;
csth.frame.frametype = AST_FRAME_VOICE;
csth.frame.subclass = AST_FORMAT_SLINEAR;
csth.frame.datalen = 320;
csth.frame.samples = 160;
start_spying(spyee, chan, &csth.spy);
ast_activate_generator(chan, &spygen, &csth);
while(spy.status == CHANSPY_RUNNING && chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee) && running == 1) {
while(csth.spy.status == CHANSPY_RUNNING && chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee) && running == 1) {
res = ast_waitfordigit(chan, 100);
if (x == sizeof(inp)) {
@ -406,16 +445,16 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
}
}
ast_deactivate_generator(chan);
stop_spying(spyee, &spy);
stop_spying(spyee, &csth.spy);
if (option_verbose >= 2)
if (option_verbose >= 2) {
ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
ast_flush_spy_queue(&spy);
}
ast_flush_spy_queue(&csth.spy);
} else {
running = 0;
}
ast_mutex_destroy(&spy.lock);
ast_mutex_destroy(&csth.spy.lock);
return running;
}
@ -423,23 +462,27 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
static int chanspy_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
struct ast_channel *peer=NULL, *prev=NULL;
char *ptr=NULL;
char name[AST_NAME_STRLEN], peer_name[AST_NAME_STRLEN];
int count=0, waitms=100, num=0;
char *args;
char name[AST_NAME_STRLEN],
peer_name[AST_NAME_STRLEN],
*args,
*ptr = NULL,
*options = NULL,
*spec = NULL,
*argv[5],
*mygroup = NULL;
int res = -1,
volfactor = 0,
silent = 0,
argc = 0,
bronly = 0,
chosen = 0,
count=0,
waitms = 100,
num = 0;
struct ast_flags flags;
char *options=NULL;
char *spec = NULL;
int volfactor=0;
int silent=0;
int argc = 0;
char *argv[5];
char *mygroup = NULL;
int bronly = 0;
int chosen = 0;
if (!(args = ast_strdupa((char *)data))) {
ast_log(LOG_ERROR, "Out of memory!\n");
@ -450,6 +493,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data)
ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
return -1;
}
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1;

Loading…
Cancel
Save