aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-23 21:52:31 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-23 21:52:31 +0000
commit265802964825de4ccd40b6c0ced3ab42ce732af4 (patch)
treeda16ea1e6e8ddeb1e8a7d2d71499c149331ce0be
parent53fc8f697e355d2e82b34feaa3037f999da1fa9a (diff)
Merge API changes for chanspy
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5238 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x.cleancount2
-rwxr-xr-xchannel.c109
-rwxr-xr-xinclude/asterisk/channel.h23
3 files changed, 130 insertions, 4 deletions
diff --git a/.cleancount b/.cleancount
index b8626c4cf..7ed6ff82d 100755
--- a/.cleancount
+++ b/.cleancount
@@ -1 +1 @@
-4
+5
diff --git a/channel.c b/channel.c
index 74862e6cd..0e93848bf 100755
--- a/channel.c
+++ b/channel.c
@@ -675,6 +675,29 @@ void ast_channel_free(struct ast_channel *chan)
ast_device_state_changed(name);
}
+static void ast_spy_detach(struct ast_channel *chan)
+{
+ struct ast_channel_spy *chanspy;
+ int to=3000;
+ int sleepms = 100;
+
+ for (chanspy = chan->spiers; chanspy; chanspy = chanspy->next) {
+ if (chanspy->status == CHANSPY_RUNNING) {
+ chanspy->status = CHANSPY_DONE;
+ }
+ }
+
+ /* signal all the spys to get lost and allow them time to unhook themselves
+ god help us if they don't......
+ */
+ while (chan->spiers && to >= 0) {
+ ast_safe_sleep(chan, sleepms);
+ to -= sleepms;
+ }
+ chan->spiers = NULL;
+ return;
+}
+
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
{
int res = 0;
@@ -699,6 +722,42 @@ int ast_softhangup(struct ast_channel *chan, int cause)
return res;
}
+static void ast_queue_spy_frame(struct ast_channel_spy *spy, struct ast_frame *f, int pos)
+{
+ struct ast_frame *tmpf = NULL;
+ int count = 0;
+
+ ast_mutex_lock(&spy->lock);
+ for (tmpf=spy->queue[pos]; tmpf && tmpf->next; tmpf=tmpf->next) {
+ count++;
+ }
+ if (count > 100) {
+ struct ast_frame *freef, *headf;
+
+ ast_log(LOG_ERROR, "Too Many frames queued at once, flushing cache.");
+ headf = spy->queue[pos];
+ /* deref the queue right away so it looks empty */
+ spy->queue[pos] = NULL;
+ tmpf = headf;
+ /* free the wasted frames */
+ while (tmpf) {
+ freef = tmpf;
+ tmpf = tmpf->next;
+ ast_frfree(freef);
+ }
+ ast_mutex_unlock(&spy->lock);
+ return;
+ }
+
+ if (tmpf) {
+ tmpf->next = ast_frdup(f);
+ } else {
+ spy->queue[pos] = ast_frdup(f);
+ }
+
+ ast_mutex_unlock(&spy->lock);
+}
+
static void free_translation(struct ast_channel *clone)
{
if (clone->writetrans)
@@ -717,6 +776,10 @@ int ast_hangup(struct ast_channel *chan)
/* Don't actually hang up a channel that will masquerade as someone else, or
if someone is going to masquerade as us */
ast_mutex_lock(&chan->lock);
+
+ /* get rid of spies */
+ ast_spy_detach(chan);
+
if (chan->masq) {
if (ast_do_masquerade(chan))
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
@@ -1344,6 +1407,12 @@ struct ast_frame *ast_read(struct ast_channel *chan)
ast_frfree(f);
f = &null_frame;
} else {
+ if (chan->spiers) {
+ struct ast_channel_spy *spying;
+ for (spying = chan->spiers; spying; spying=spying->next) {
+ ast_queue_spy_frame(spying, f, 0);
+ }
+ }
if (chan->monitor && chan->monitor->read_stream ) {
#ifndef MONITOR_CONSTANT_DELAY
int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
@@ -2780,6 +2849,18 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
}
}
+
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c0->_softhangup = 0;
+ if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c1->_softhangup = 0;
+ c0->_bridge = c1;
+ c1->_bridge = c0;
+ ast_log(LOG_DEBUG, "UNBRIDGE SIGNAL RECEIVED! ENDING NATIVE BRIDGE IF IT EXISTS.\n");
+ continue;
+ }
+
/* Stop if we're a zombie or need a soft hangup */
if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) {
*fo = NULL;
@@ -2789,10 +2870,12 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
break;
}
if (c0->tech->bridge && config->timelimit==0 &&
- (c0->tech->bridge == c1->tech->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
+ (c0->tech->bridge == c1->tech->bridge) && !nativefailed && !c0->monitor && !c1->monitor && !c0->spiers && !c1->spiers) {
/* Looks like they share a bridge code */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
+ ast_set_flag(c0, AST_FLAG_NBRIDGE);
+ ast_set_flag(c1, AST_FLAG_NBRIDGE);
if (!(res = c0->tech->bridge(c0, c1, config->flags, fo, rc))) {
c0->_bridge = NULL;
c1->_bridge = NULL;
@@ -2803,8 +2886,20 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
"Uniqueid2: %s\r\n",
c0->name, c1->name, c0->uniqueid, c1->uniqueid);
ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
+ ast_clear_flag(c0, AST_FLAG_NBRIDGE);
+ ast_clear_flag(c1, AST_FLAG_NBRIDGE);
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
+ c0->_bridge = c1;
+ c1->_bridge = c0;
+ continue;
+ }
+ else
return 0;
+ } else {
+ ast_clear_flag(c0, AST_FLAG_NBRIDGE);
+ ast_clear_flag(c1, AST_FLAG_NBRIDGE);
}
+
/* If they return non-zero then continue on normally. Let "-2" mean don't worry about
my not wanting to bridge */
if ((res != -2) && (res != -3))
@@ -2825,11 +2920,22 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
return -1;
}
o0nativeformats = c0->nativeformats;
+
o1nativeformats = c1->nativeformats;
}
who = ast_waitfor_n(cs, 2, &to);
if (!who) {
ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c0->_softhangup = 0;
+ if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c1->_softhangup = 0;
+ c0->_bridge = c1;
+ c1->_bridge = c0;
+ continue;
+ }
+
continue;
}
f = ast_read(who);
@@ -2858,6 +2964,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
(f->frametype == AST_FRAME_IMAGE) ||
(f->frametype == AST_FRAME_HTML) ||
(f->frametype == AST_FRAME_DTMF)) {
+
if ((f->frametype == AST_FRAME_DTMF) &&
(config->flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
if ((who == c0)) {
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 25b483b11..a28135c12 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -152,14 +152,27 @@ struct ast_channel_tech {
struct ast_channel *(* const bridged_channel)(struct ast_channel *chan, struct ast_channel *bridge);
};
+
+#define CHANSPY_NEW 0
+#define CHANSPY_RUNNING 1
+#define CHANSPY_DONE 2
+
+struct ast_channel_spy {
+ struct ast_frame *queue[2];
+ ast_mutex_t lock;
+ char status;
+ struct ast_channel_spy *next;
+};
+
+
/*! Main Channel structure associated with a channel. */
/*!
* This is the side of it mostly used by the pbx and call management.
*/
struct ast_channel {
/*! ASCII Description of channel name */
- char name[AST_CHANNEL_NAME];
-
+ char name[AST_CHANNEL_NAME];
+
/*! Technology */
const struct ast_channel_tech *tech;
/*! Private data used by the technology driver */
@@ -313,6 +326,9 @@ struct ast_channel {
/*! Raw write format */
int rawwriteformat;
+ /*! Chan Spy stuff */
+ struct ast_channel_spy *spiers;
+
/*! For easy linking */
struct ast_channel *next;
@@ -329,6 +345,8 @@ struct ast_channel {
#define AST_FLAG_ZOMBIE (1 << 4) /* if we are a zombie */
#define AST_FLAG_EXCEPTION (1 << 5) /* if there is a pending exception */
#define AST_FLAG_MOH (1 << 6) /* XXX anthm promises me this will disappear XXX listening to moh */
+#define AST_FLAG_SPYING (1 << 7) /* XXX might also go away XXX is spying on someone */
+#define AST_FLAG_NBRIDGE (1 << 8) /* is it in a native bridge */
#define AST_FEATURE_PLAY_WARNING (1 << 0)
#define AST_FEATURE_REDIRECT (1 << 1)
@@ -389,6 +407,7 @@ struct outgoing_helper {
#define AST_SOFTHANGUP_TIMEOUT (1 << 3)
#define AST_SOFTHANGUP_APPUNLOAD (1 << 4)
#define AST_SOFTHANGUP_EXPLICIT (1 << 5)
+#define AST_SOFTHANGUP_UNBRIDGE (1 << 6)
/* Bits 0-15 of state are reserved for the state (up/down) of the line */
/*! Channel is down and available */