diff options
-rw-r--r-- | channels/chan_sip.c | 2 | ||||
-rw-r--r-- | include/asterisk/stasis_app.h | 10 | ||||
-rw-r--r-- | main/Makefile | 20 | ||||
-rw-r--r-- | main/core_unreal.c | 2 | ||||
-rw-r--r-- | main/utils.c | 2 | ||||
-rw-r--r-- | res/ari/resource_bridges.c | 9 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 15 | ||||
-rw-r--r-- | res/res_stasis.c | 22 | ||||
-rw-r--r-- | res/res_stasis_playback.c | 2 | ||||
-rw-r--r-- | res/res_stasis_recording.c | 20 | ||||
-rw-r--r-- | res/stasis/control.c | 75 | ||||
-rw-r--r-- | res/stasis/control.h | 18 |
12 files changed, 133 insertions, 64 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 09ab1a196..ffc2084a1 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -13531,7 +13531,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 50fdc5739..d52c3f0a7 100644 --- a/main/Makefile +++ b/main/Makefile @@ -225,11 +225,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 @@ -305,11 +305,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 da0bb43bb..1f5c202ba 100644 --- a/main/core_unreal.c +++ b/main/core_unreal.c @@ -805,9 +805,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 6a778b90c..e92f5c3d9 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1153,7 +1153,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 7b9b94665..6018c43be 100644 --- a/res/ari/resource_bridges.c +++ b/res/ari/resource_bridges.c @@ -296,10 +296,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; } @@ -526,9 +527,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 45bc3103a..9cc9f92a9 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 63c565d44..5aa0aa9ac 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 74336abdc..97191c26d 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 dcabfa699..af5c41e87 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 41d538cbe..86f94423d 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 */ |