summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_sip.c2
-rw-r--r--include/asterisk/stasis_app.h10
-rw-r--r--main/Makefile20
-rw-r--r--main/core_unreal.c2
-rw-r--r--main/utils.c2
-rw-r--r--res/ari/resource_bridges.c9
-rw-r--r--res/res_rtp_asterisk.c15
-rw-r--r--res/res_stasis.c22
-rw-r--r--res/res_stasis_playback.c2
-rw-r--r--res/res_stasis_recording.c20
-rw-r--r--res/stasis/control.c75
-rw-r--r--res/stasis/control.h18
12 files changed, 133 insertions, 64 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 83d3ea0eb..91fb0b546 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -13530,7 +13530,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
}
/* Finally our remaining audio/video codecs */
- for (x = 0; ast_test_flag(&p->flags[0], SIP_OUTGOING) && x < ast_format_cap_count(p->caps); x++) {
+ for (x = 0; p->outgoing_call && x < ast_format_cap_count(p->caps); x++) {
tmp_fmt = ast_format_cap_get_format(p->caps, x);
if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index f2b07e0bf..90ef82ebf 100644
--- a/include/asterisk/stasis_app.h
+++ b/include/asterisk/stasis_app.h
@@ -440,6 +440,16 @@ int stasis_app_control_is_done(
struct stasis_app_control *control);
/*!
+ * \brief Flush the control command queue.
+ * \since 13.9.0
+ *
+ * \param control Control object to flush command queue.
+ *
+ * \return Nothing
+ */
+void stasis_app_control_flush_queue(struct stasis_app_control *control);
+
+/*!
* \brief Returns the uniqueid of the channel associated with this control
*
* \param control Control object.
diff --git a/main/Makefile b/main/Makefile
index 70b2a3900..a64eabcde 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -224,11 +224,11 @@ endif
$(ASTSSL_LIB): $(ASTSSL_LIB).$(ASTSSL_SO_VERSION)
$(ECHO_PREFIX) echo " [LN] $< -> $@"
-ifneq ($(LDCONFIG),)
- $(CMD_PREFIX) $(LDCONFIG) $(LDCONFIG_FLAGS) . 2>/dev/null
-else
- $(CMD_PREFIX) $(LN) -sf $< $@
-endif
+ $(CMD_PREFIX) if [ -x "$(LDCONFIG)" ] ; then \
+ $(LDCONFIG) $(LDCONFIG_FLAGS) . 2>/dev/null ;\
+ else \
+ $(LN) -sf $< $@ ;\
+ fi
else # Darwin
ASTSSL_LIB:=libasteriskssl.dylib
@@ -304,11 +304,11 @@ $(ASTPJ_LIB).$(ASTPJ_SO_VERSION): libasteriskpj.o libasteriskpj.exports
$(ASTPJ_LIB): $(ASTPJ_LIB).$(ASTPJ_SO_VERSION)
$(ECHO_PREFIX) echo " [LN] $< -> $@"
-ifneq ($(LDCONFIG),)
- $(CMD_PREFIX) $(LDCONFIG) $(LDCONFIG_FLAGS) . 2>/dev/null
-else
- $(CMD_PREFIX) $(LN) -sf $< $@
-endif
+ $(CMD_PREFIX) if [ -x "$(LDCONFIG)" ] ; then \
+ $(LDCONFIG) $(LDCONFIG_FLAGS) . 2>/dev/null ;\
+ else \
+ $(LN) -sf $< $@ ;\
+ fi
else # Darwin
ASTPJ_LIB:=libasteriskpj.dylib
diff --git a/main/core_unreal.c b/main/core_unreal.c
index 028e371f6..fc311ec5d 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -808,9 +808,11 @@ int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge
return -1;
}
+ /* The bridge thread now controls the chan ref from the ast_unreal_pvt */
ao2_lock(p);
ast_set_flag(p, AST_UNREAL_CARETAKER_THREAD);
ao2_unlock(p);
+
ast_channel_unref(chan);
return 0;
diff --git a/main/utils.c b/main/utils.c
index 686af6b2f..9a400d9db 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1158,7 +1158,7 @@ static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_
"Usage: core show locks\n"
" This command is for lock debugging. It prints out which locks\n"
"are owned by each active thread.\n";
- ast_cli_allow_on_shutdown(e);
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index ad37053f7..a37b83146 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -297,10 +297,11 @@ static void *bridge_channel_control_thread(void *data)
thread_data = NULL;
stasis_app_control_execute_until_exhausted(bridge_channel, control);
+ stasis_app_control_flush_queue(control);
- ast_hangup(bridge_channel);
- ao2_cleanup(control);
stasis_forward_cancel(forward);
+ ao2_cleanup(control);
+ ast_hangup(bridge_channel);
return NULL;
}
@@ -527,9 +528,7 @@ static enum play_found_result ari_bridges_play_found(const char *args_media,
control = stasis_app_control_find_by_channel(play_channel);
if (!control) {
- ast_ari_response_error(
- response, 500, "Internal Error", "Failed to get control snapshot");
- return PLAY_FOUND_FAILURE;
+ return PLAY_FOUND_CHANNEL_UNAVAILABLE;
}
ao2_lock(control);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 4c6ee185f..029aff01b 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -2252,7 +2252,6 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
int res;
- int hdrlen = 12;
*ice = 0;
@@ -2260,9 +2259,6 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
return -1;
}
- rtp->txcount++;
- rtp->txoctetcount += (len - hdrlen);
-
#ifdef HAVE_PJPROJECT
if (rtp->ice) {
pj_thread_register_check();
@@ -2289,7 +2285,16 @@ static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
{
- return __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1);
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ int hdrlen = 12;
+ int res;
+
+ if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
+ rtp->txcount++;
+ rtp->txoctetcount += (res - hdrlen);
+ }
+
+ return res;
}
static int rtp_get_rate(struct ast_format *format)
diff --git a/res/res_stasis.c b/res/res_stasis.c
index 94b037e69..fae9aa220 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -1179,6 +1179,11 @@ int stasis_app_control_is_done(struct stasis_app_control *control)
return control_is_done(control);
}
+void stasis_app_control_flush_queue(struct stasis_app_control *control)
+{
+ control_flush_queue(control);
+}
+
struct ast_datastore_info set_end_published_info = {
.type = "stasis_end_published",
};
@@ -1188,10 +1193,11 @@ void stasis_app_channel_set_stasis_end_published(struct ast_channel *chan)
struct ast_datastore *datastore;
datastore = ast_datastore_alloc(&set_end_published_info, NULL);
-
- ast_channel_lock(chan);
- ast_channel_datastore_add(chan, datastore);
- ast_channel_unlock(chan);
+ if (datastore) {
+ ast_channel_lock(chan);
+ ast_channel_datastore_add(chan, datastore);
+ ast_channel_unlock(chan);
+ }
}
int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan)
@@ -1211,12 +1217,11 @@ static void remove_stasis_end_published(struct ast_channel *chan)
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &set_end_published_info, NULL);
- ast_channel_unlock(chan);
-
if (datastore) {
ast_channel_datastore_remove(chan, datastore);
ast_datastore_free(datastore);
}
+ ast_channel_unlock(chan);
}
/*! /brief Stasis dialplan application callback */
@@ -1371,6 +1376,11 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
remove_stasis_end_published(chan);
}
+ control_flush_queue(control);
+
+ /* Stop any lingering silence generator */
+ control_silence_stop_now(control);
+
/* There's an off chance that app is ready for cleanup. Go ahead
* and clean up, just in case
*/
diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c
index 779dd7755..7fdb5d4ad 100644
--- a/res/res_stasis_playback.c
+++ b/res/res_stasis_playback.c
@@ -118,6 +118,7 @@ static void playback_dtor(void *obj)
{
struct stasis_app_playback *playback = obj;
+ ao2_cleanup(playback->control);
ast_string_field_free_memory(playback);
}
@@ -143,6 +144,7 @@ static struct stasis_app_playback *playback_create(
ast_string_field_set(playback, id, uuid);
}
+ ao2_ref(control, +1);
playback->control = control;
ao2_ref(playback, +1);
diff --git a/res/res_stasis_recording.c b/res/res_stasis_recording.c
index 392d92c8e..46bc6eb71 100644
--- a/res/res_stasis_recording.c
+++ b/res/res_stasis_recording.c
@@ -265,7 +265,13 @@ static enum stasis_app_control_channel_result check_rule_recording(
return STASIS_APP_CHANNEL_RECORDING;
}
-struct stasis_app_control_rule rule_recording = {
+/*
+ * XXX This only works because there is one and only one rule in
+ * the system so it can be added to any number of channels
+ * without issue. However, as soon as there is another rule then
+ * watch out for weirdness because of cross linked lists.
+ */
+static struct stasis_app_control_rule rule_recording = {
.check_rule = check_rule_recording
};
@@ -358,6 +364,7 @@ static void recording_dtor(void *obj)
struct stasis_app_recording *recording = obj;
ast_free(recording->absolute_name);
+ ao2_cleanup(recording->control);
ao2_cleanup(recording->options);
}
@@ -413,6 +420,7 @@ struct stasis_app_recording *stasis_app_control_record(
ao2_ref(options, +1);
recording->options = options;
+ ao2_ref(control, +1);
recording->control = control;
recording->state = STASIS_APP_RECORDING_STATE_QUEUED;
@@ -465,15 +473,7 @@ const char *stasis_app_recording_get_name(
struct stasis_app_recording *stasis_app_recording_find_by_name(const char *name)
{
- RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
-
- recording = ao2_find(recordings, name, OBJ_KEY);
- if (recording == NULL) {
- return NULL;
- }
-
- ao2_ref(recording, +1);
- return recording;
+ return ao2_find(recordings, name, OBJ_KEY);
}
struct ast_json *stasis_app_recording_to_json(
diff --git a/res/stasis/control.c b/res/stasis/control.c
index ebb7e0194..97b0b8809 100644
--- a/res/stasis/control.c
+++ b/res/stasis/control.c
@@ -87,21 +87,19 @@ static void control_dtor(void *obj)
{
struct stasis_app_control *control = obj;
- AST_LIST_HEAD_DESTROY(&control->add_rules);
- AST_LIST_HEAD_DESTROY(&control->remove_rules);
+ ao2_cleanup(control->command_queue);
- /* We may have a lingering silence generator; free it */
- ast_channel_stop_silence_generator(control->channel, control->silgen);
- control->silgen = NULL;
+ ast_channel_cleanup(control->channel);
+ ao2_cleanup(control->app);
- ao2_cleanup(control->command_queue);
ast_cond_destroy(&control->wait_cond);
- ao2_cleanup(control->app);
+ AST_LIST_HEAD_DESTROY(&control->add_rules);
+ AST_LIST_HEAD_DESTROY(&control->remove_rules);
}
struct stasis_app_control *control_create(struct ast_channel *channel, struct stasis_app *app)
{
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ struct stasis_app_control *control;
int res;
control = ao2_alloc(sizeof(*control), control_dtor);
@@ -109,28 +107,29 @@ struct stasis_app_control *control_create(struct ast_channel *channel, struct st
return NULL;
}
- control->app = ao2_bump(app);
+ AST_LIST_HEAD_INIT(&control->add_rules);
+ AST_LIST_HEAD_INIT(&control->remove_rules);
res = ast_cond_init(&control->wait_cond, NULL);
if (res != 0) {
ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
strerror(errno));
+ ao2_ref(control, -1);
return NULL;
}
+ control->app = ao2_bump(app);
+
+ ast_channel_ref(channel);
+ control->channel = channel;
+
control->command_queue = ao2_container_alloc_list(
AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
-
if (!control->command_queue) {
+ ao2_ref(control, -1);
return NULL;
}
- control->channel = channel;
-
- AST_LIST_HEAD_INIT(&control->add_rules);
- AST_LIST_HEAD_INIT(&control->remove_rules);
-
- ao2_ref(control, +1);
return control;
}
@@ -252,6 +251,11 @@ static struct stasis_app_command *exec_command_on_condition(
}
ao2_lock(control->command_queue);
+ if (control->is_done) {
+ ao2_unlock(control->command_queue);
+ ao2_ref(command, -1);
+ return NULL;
+ }
if (can_exec_fn && (retval = can_exec_fn(control))) {
ao2_unlock(control->command_queue);
command_complete(command, retval);
@@ -403,7 +407,10 @@ int control_is_done(struct stasis_app_control *control)
void control_mark_done(struct stasis_app_control *control)
{
+ /* Locking necessary to sync with other threads adding commands to the queue. */
+ ao2_lock(control->command_queue);
control->is_done = 1;
+ ao2_unlock(control->command_queue);
}
struct stasis_app_control_continue_data {
@@ -428,7 +435,7 @@ static int app_control_continue(struct stasis_app_control *control,
/* Called from stasis_app_exec thread; no lock needed */
ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
- control->is_done = 1;
+ control_mark_done(control);
return 0;
}
@@ -785,8 +792,7 @@ void stasis_app_control_silence_start(struct stasis_app_control *control)
stasis_app_send_command_async(control, app_control_silence_start, NULL, NULL);
}
-static int app_control_silence_stop(struct stasis_app_control *control,
- struct ast_channel *chan, void *data)
+void control_silence_stop_now(struct stasis_app_control *control)
{
if (control->silgen) {
ast_debug(3, "%s: Stopping silence generator\n",
@@ -795,7 +801,12 @@ static int app_control_silence_stop(struct stasis_app_control *control,
control->channel, control->silgen);
control->silgen = NULL;
}
+}
+static int app_control_silence_stop(struct stasis_app_control *control,
+ struct ast_channel *chan, void *data)
+{
+ control_silence_stop_now(control);
return 0;
}
@@ -1112,24 +1123,36 @@ int stasis_app_control_queue_control(struct stasis_app_control *control,
return ast_queue_control(control->channel, frame_type);
}
+void control_flush_queue(struct stasis_app_control *control)
+{
+ struct ao2_iterator iter;
+ struct stasis_app_command *command;
+
+ iter = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
+ while ((command = ao2_iterator_next(&iter))) {
+ command_complete(command, -1);
+ ao2_ref(command, -1);
+ }
+ ao2_iterator_destroy(&iter);
+}
+
int control_dispatch_all(struct stasis_app_control *control,
struct ast_channel *chan)
{
int count = 0;
- struct ao2_iterator i;
- void *obj;
+ struct ao2_iterator iter;
+ struct stasis_app_command *command;
ast_assert(control->channel == chan);
- i = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
-
- while ((obj = ao2_iterator_next(&i))) {
- RAII_VAR(struct stasis_app_command *, command, obj, ao2_cleanup);
+ iter = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
+ while ((command = ao2_iterator_next(&iter))) {
command_invoke(command, control, chan);
+ ao2_ref(command, -1);
++count;
}
+ ao2_iterator_destroy(&iter);
- ao2_iterator_destroy(&i);
return count;
}
diff --git a/res/stasis/control.h b/res/stasis/control.h
index a139f82e4..1d37a494a 100644
--- a/res/stasis/control.h
+++ b/res/stasis/control.h
@@ -41,6 +41,16 @@
struct stasis_app_control *control_create(struct ast_channel *channel, struct stasis_app *app);
/*!
+ * \brief Flush the control command queue.
+ * \since 13.9.0
+ *
+ * \param control Control object to flush command queue.
+ *
+ * \return Nothing
+ */
+void control_flush_queue(struct stasis_app_control *control);
+
+/*!
* \brief Dispatch all commands enqueued to this control.
*
* \param control Control object to dispatch.
@@ -108,5 +118,13 @@ int control_add_channel_to_bridge(
struct stasis_app_control *control,
struct ast_channel *chan, void *obj);
+/*!
+ * \brief Stop playing silence to a channel right now.
+ * \since 13.9.0
+ *
+ * \param control The control for chan
+ */
+void control_silence_stop_now(struct stasis_app_control *control);
+
#endif /* _ASTERISK_RES_STASIS_CONTROL_H */