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); AST_MUTEX_DEFINE_STATIC(modlock);
#define ast_fit_in_short(in) (in < -32768 ? -32768 : in > 32767 ? 32767 : in) #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 AST_NAME_STRLEN 256
#define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret; #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 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 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 *synopsis = "Tap into any type of asterisk channel and listen to audio";
static char *app = "ChanSpy"; static char *app = "ChanSpy";
@ -69,14 +67,28 @@ AST_DECLARE_OPTIONS(chanspy_opts,{
}); });
STANDARD_LOCAL_USER; STANDARD_LOCAL_USER;
LOCAL_USER_DECL; LOCAL_USER_DECL;
struct chanspy_translation_helper { struct chanspy_translation_helper {
/* spy data */
struct ast_channel_spy spy;
/* read frame */
int fmt0;
short buf0[CS_BUFLEN];
struct ast_trans_pvt *trans0; struct ast_trans_pvt *trans0;
/* write frame */
int fmt1;
struct ast_trans_pvt *trans1; struct ast_trans_pvt *trans1;
short buf1[CS_BUFLEN];
/* muxed frame */
struct ast_frame frame;
short buf[CS_BUFLEN];
int volfactor; int volfactor;
struct ast_channel_spy *spy;
}; };
/* Prototypes */ /* 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) static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
{ {
struct ast_frame *f0, *f1, write_frame, *f; struct ast_frame *f, *f0, *f1;
int x=0, framelen_a = 0, framelen_b = 0, size = 0; int x = 0, vf = 0;
short buf[CS_BUFLEN], buf0[CS_BUFLEN], buf1[CS_BUFLEN];
struct chanspy_translation_helper *csth = data; 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);
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;
}
} 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) {
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;
}
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;
} }
}
memset(buf, 0, sizeof(buf)); if (csth->fmt1 && csth->fmt1 != AST_FORMAT_SLINEAR && !csth->trans1) {
memset(buf0, 0, sizeof(buf0)); if (csth->fmt1 == csth->fmt0 && csth->trans0) {
memset(buf1, 0, sizeof(buf1)); 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 (csth->trans0) {
if ((f = ast_translate(csth->trans0, f0, 0))) { if ((f = ast_translate(csth->trans0, f0, 0))) {
framelen_a = f->datalen * sizeof(short); memcpy(csth->buf0, f->data, f->datalen * sizeof(short));
memcpy(buf0, f->data, framelen_a);
ast_frfree(f); ast_frfree(f);
} else } else {
return 0; return 0;
}
} else { } else {
framelen_a = f0->datalen * sizeof(short); memcpy(csth->buf0, f0->data, f0->datalen * sizeof(short));
memcpy(buf0, f0->data, framelen_a);
} }
}
if (f1) {
if (csth->trans1) { if (csth->trans1) {
if ((f = ast_translate(csth->trans1, f1, 0))) { if ((f = ast_translate(csth->trans1, f1, 0))) {
framelen_b = f->datalen * sizeof(short); memcpy(csth->buf1, f->data, f->datalen * sizeof(short));
memcpy(buf1, f->data, framelen_b);
ast_frfree(f); ast_frfree(f);
} else } else {
return 0; return 0;
}
} else { } else {
framelen_b = f1->datalen * sizeof(short); memcpy(csth->buf1, f1->data, f1->datalen * sizeof(short));
memcpy(buf1, f1->data, framelen_b);
} }
size = find_smallest_of_three(len, framelen_a, framelen_b); }
vf = get_volfactor(csth->volfactor); vf = get_volfactor(csth->volfactor);
vf = minmax(vf, 16); vf = minmax(vf, 16);
for(x=0; x < size; x++) { for(x=0; x < len; x++) {
if (vf < 0) { if (vf < 0) {
buf0[x] /= abs(vf); if (f0) {
buf1[x] /= abs(vf); csth->buf0[x] /= abs(vf);
} else if (vf > 0) { }
buf0[x] *= vf; if (f1) {
buf1[x] *= vf; 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)); if (f0 && f1) {
write_frame.frametype = AST_FRAME_VOICE; csth->buf[x] = ast_fit_in_short(csth->buf0[x] + csth->buf1[x]);
write_frame.subclass = AST_FORMAT_SLINEAR; } else if (f0) {
write_frame.datalen = size; csth->buf[x] = csth->buf0[x];
write_frame.samples = size; } else if (f1) {
write_frame.data = buf; csth->buf[x] = csth->buf1[x];
write_frame.offset = 0;
ast_write(chan, &write_frame);
} else {
nc++;
if(nc > 1) {
return -1;
} }
} }
if (f0) csth->frame.data = csth->buf;
ast_write(chan, &csth->frame);
if (f0) {
ast_frfree(f0); ast_frfree(f0);
if (f1) }
if (f1) {
ast_frfree(f1); ast_frfree(f1);
}
return 0; return 0;
} }
static struct ast_generator spygen = { static struct ast_generator spygen = {
@ -356,7 +395,6 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
int running = 1, res = 0, x = 0; int running = 1, res = 0, x = 0;
char inp[24]; char inp[24];
char *name=NULL; char *name=NULL;
struct ast_channel_spy spy;
if (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee)) { if (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee)) {
memset(inp, 0, sizeof(inp)); memset(inp, 0, sizeof(inp));
@ -364,17 +402,18 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
if (option_verbose >= 2) if (option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name); 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)); memset(&csth, 0, sizeof(csth));
csth.spy.status = CHANSPY_RUNNING;
ast_mutex_init(&csth.spy.lock);
csth.volfactor = *volfactor; 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); 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); res = ast_waitfordigit(chan, 100);
if (x == sizeof(inp)) { 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); 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_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
}
ast_flush_spy_queue(&spy); ast_flush_spy_queue(&csth.spy);
} else { } else {
running = 0; running = 0;
} }
ast_mutex_destroy(&spy.lock); ast_mutex_destroy(&csth.spy.lock);
return running; 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) static int chanspy_exec(struct ast_channel *chan, void *data)
{ {
int res=-1;
struct localuser *u; struct localuser *u;
struct ast_channel *peer=NULL, *prev=NULL; struct ast_channel *peer=NULL, *prev=NULL;
char *ptr=NULL; char name[AST_NAME_STRLEN],
char name[AST_NAME_STRLEN], peer_name[AST_NAME_STRLEN]; peer_name[AST_NAME_STRLEN],
int count=0, waitms=100, num=0; *args,
char *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; 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))) { if (!(args = ast_strdupa((char *)data))) {
ast_log(LOG_ERROR, "Out of memory!\n"); 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"); ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
return -1; return -1;
} }
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1; return -1;

Loading…
Cancel
Save