diff options
-rw-r--r-- | autoconf/ast_check_pwlib.m4 | 4 | ||||
-rw-r--r-- | codecs/codecs.xml | 1 | ||||
-rw-r--r-- | codecs/gsm/src/short_term.c | 16 | ||||
-rwxr-xr-x | configure | 10 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | main/translate.c | 14 | ||||
-rw-r--r-- | res/res_pjsip.c | 7 | ||||
-rw-r--r-- | res/res_pjsip_endpoint_identifier_ip.c | 120 | ||||
-rw-r--r-- | res/res_stasis.c | 226 | ||||
-rw-r--r-- | res/stasis/app.c | 193 | ||||
-rw-r--r-- | res/stasis/command.c | 13 | ||||
-rw-r--r-- | res/stasis/control.c | 58 | ||||
-rw-r--r-- | res/stasis/stasis_bridge.c | 3 |
13 files changed, 430 insertions, 241 deletions
diff --git a/autoconf/ast_check_pwlib.m4 b/autoconf/ast_check_pwlib.m4 index 510881f3c..beaf8db74 100644 --- a/autoconf/ast_check_pwlib.m4 +++ b/autoconf/ast_check_pwlib.m4 @@ -103,7 +103,7 @@ if test "${HAS_PWLIB:-unset}" = "unset" ; then else AC_CHECK_HEADER(/usr/local/include/ptlib.h, HAS_PWLIB=1, ) if test "${HAS_PWLIB:-unset}" != "unset" ; then - AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/bin$PATH_SEPARATOR/usr/local/share/pwlib/make) + AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/bin$PATH_SEPARATOR/usr/local/share/ptlib/make$PATH_SEPARATOR/usr/local/share/pwlib/make) PWLIB_INCDIR="/usr/local/include" PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir 2>/dev/null` if test "${PWLIB_LIBDIR:-unset}" = "unset"; then @@ -121,7 +121,7 @@ if test "${HAS_PWLIB:-unset}" = "unset" ; then else AC_CHECK_HEADER(/usr/include/ptlib.h, HAS_PWLIB=1, ) if test "${HAS_PWLIB:-unset}" != "unset" ; then - AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/bin$PATH_SEPARATOR/usr/share/pwlib/make) + AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/bin$PATH_SEPARATOR/usr/share/ptlib/make$PATH_SEPARATOR/usr/share/pwlib/make) PWLIB_INCDIR="/usr/include" PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir 2>/dev/null` if test "${PWLIB_LIBDIR:-unset}" = "unset"; then diff --git a/codecs/codecs.xml b/codecs/codecs.xml index c3ccf00f1..0b4e2a474 100644 --- a/codecs/codecs.xml +++ b/codecs/codecs.xml @@ -3,7 +3,6 @@ <depend>xmlstarlet</depend> <depend>bash</depend> <depend>res_format_attr_opus</depend> - <depend>curl</depend> <defaultenabled>no</defaultenabled> </member> <member name="codec_silk" displayname="Download the SILK codec from Digium. See http://downloads.digium.com/pub/telephony/codec_silk/README."> diff --git a/codecs/gsm/src/short_term.c b/codecs/gsm/src/short_term.c index 4172d322c..d22d276ba 100644 --- a/codecs/gsm/src/short_term.c +++ b/codecs/gsm/src/short_term.c @@ -55,21 +55,21 @@ static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp), */ #undef STEP -#define STEP( B, MIC, INVA ) \ +#define STEP( B_TIMES_TWO, MIC, INVA ) \ temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ - temp1 = GSM_SUB( temp1, B << 1 ); \ + temp1 = GSM_SUB( temp1, B_TIMES_TWO ); \ temp1 = (word)GSM_MULT_R( INVA, temp1 ); \ *LARpp++ = GSM_ADD( temp1, temp1 ); STEP( 0, -32, 13107 ); STEP( 0, -32, 13107 ); - STEP( 2048, -16, 13107 ); - STEP( -2560, -16, 13107 ); + STEP( 4096, -16, 13107 ); + STEP( -5120, -16, 13107 ); - STEP( 94, -8, 19223 ); - STEP( -1792, -8, 17476 ); - STEP( -341, -4, 31454 ); - STEP( -1144, -4, 29708 ); + STEP( 188, -8, 19223 ); + STEP( -3584, -8, 17476 ); + STEP( -682, -4, 31454 ); + STEP( -2288, -4, 29708 ); /* NOTE: the addition of *MIC is used to restore * the sign of *LARc. @@ -18425,7 +18425,7 @@ LDFLAGS="${saved_sanitize_LDFLAGS}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wdeclaration-after-statement support" >&5 $as_echo_n "checking for -Wdeclaration-after-statement support... " >&6; } -if $(${CC} -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wdeclaration-after-statement -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } AST_DECLARATION_AFTER_STATEMENT=-Wdeclaration-after-statement @@ -18477,7 +18477,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wno-format-truncation" >&5 $as_echo_n "checking for -Wno-format-truncation... " >&6; } -if $(${CC} -O2 -Wno-format-truncation -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wno-format-truncation -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } AST_NO_FORMAT_TRUNCATION=-Wno-format-truncation @@ -18490,7 +18490,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wshadow" >&5 $as_echo_n "checking for -Wshadow... " >&6; } -if $(${CC} -Wshadow -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wshadow -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } AST_SHADOW_WARNINGS=-Wshadow @@ -28858,7 +28858,7 @@ else ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /usr/local/bin$PATH_SEPARATOR/usr/local/share/pwlib/make +for as_dir in /usr/local/bin$PATH_SEPARATOR/usr/local/share/ptlib/make$PATH_SEPARATOR/usr/local/share/pwlib/make do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. @@ -28920,7 +28920,7 @@ else ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /usr/bin$PATH_SEPARATOR/usr/share/pwlib/make +for as_dir in /usr/bin$PATH_SEPARATOR/usr/share/ptlib/make$PATH_SEPARATOR/usr/share/pwlib/make do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. diff --git a/configure.ac b/configure.ac index c617cf084..e333fafa1 100644 --- a/configure.ac +++ b/configure.ac @@ -1196,7 +1196,7 @@ LDFLAGS="${saved_sanitize_LDFLAGS}" AC_SUBST(AST_UNDEFINED_SANITIZER) AC_MSG_CHECKING(for -Wdeclaration-after-statement support) -if $(${CC} -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wdeclaration-after-statement -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then AC_MSG_RESULT(yes) AST_DECLARATION_AFTER_STATEMENT=-Wdeclaration-after-statement else @@ -1236,7 +1236,7 @@ fi AC_SUBST(AST_NO_STRICT_OVERFLOW) AC_MSG_CHECKING(for -Wno-format-truncation) -if $(${CC} -O2 -Wno-format-truncation -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wno-format-truncation -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then AC_MSG_RESULT(yes) AST_NO_FORMAT_TRUNCATION=-Wno-format-truncation else @@ -1246,7 +1246,7 @@ fi AC_SUBST(AST_NO_FORMAT_TRUNCATION) AC_MSG_CHECKING(for -Wshadow) -if $(${CC} -Wshadow -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then +if $(${CC} -Wshadow -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then AC_MSG_RESULT(yes) AST_SHADOW_WARNINGS=-Wshadow else diff --git a/main/translate.c b/main/translate.c index 0721f07b0..240e4956a 100644 --- a/main/translate.c +++ b/main/translate.c @@ -34,7 +34,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <sys/time.h> #include <sys/resource.h> #include <math.h> -#include <stdlib.h> #include "asterisk/lock.h" #include "asterisk/channel.h" @@ -1322,6 +1321,13 @@ void ast_translator_deactivate(struct ast_translator *t) AST_RWLIST_UNLOCK(&translators); } +/*! Calculate the absolute difference between sample rate of two formats. */ +#define format_sample_rate_absdiff(fmt1, fmt2) ({ \ + unsigned int rate1 = ast_format_get_sample_rate(fmt1); \ + unsigned int rate2 = ast_format_get_sample_rate(fmt2); \ + (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \ +}) + /*! \brief Calculate our best translator source format, given costs, and a desired destination */ int ast_translator_best_choice(struct ast_format_cap *dst_cap, struct ast_format_cap *src_cap, @@ -1406,10 +1412,8 @@ int ast_translator_best_choice(struct ast_format_cap *dst_cap, beststeps = matrix_get(x, y)->multistep; } else if (matrix_get(x, y)->table_cost == besttablecost && matrix_get(x, y)->multistep == beststeps) { - int gap_selected = abs(ast_format_get_sample_rate(best) - - ast_format_get_sample_rate(bestdst)); - int gap_current = abs(ast_format_get_sample_rate(src) - - ast_format_get_sample_rate(dst)); + unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst); + unsigned int gap_current = format_sample_rate_absdiff(src, dst); if (gap_current < gap_selected) { /* better than what we have so far */ diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 392f9a6f2..842cc20e3 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2573,13 +2573,13 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident id_list_item = ast_calloc(1, sizeof(*id_list_item)); if (!id_list_item) { - ast_log(LOG_ERROR, "Unabled to add endpoint identifier. Out of memory.\n"); + ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n"); return -1; } id_list_item->identifier = identifier; id_list_item->name = name; - ast_debug(1, "Register endpoint identifier %s (%p)\n", name, identifier); + ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier); if (ast_strlen_zero(name)) { /* if an identifier has no name then place in front */ @@ -2602,7 +2602,8 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident id_list_item->priority = 0; while ((current = strchr(current, ','))) { ++id_list_item->priority; - if (!strncmp(prev, name, current - prev)) { + if (!strncmp(prev, name, current - prev) + && strlen(name) == current - prev) { break; } prev = ++current; diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c index 14716234a..14f4cfd1a 100644 --- a/res/res_pjsip_endpoint_identifier_ip.c +++ b/res/res_pjsip_endpoint_identifier_ip.c @@ -105,7 +105,7 @@ struct ip_identify_match { struct ast_ha *matches; /*! \brief Perform SRV resolution of hostnames */ unsigned int srv_lookups; - /*! \brief Hosts to be resolved after applying configuration */ + /*! \brief Hosts to be resolved when applying configuration */ struct ao2_container *hosts; }; @@ -150,8 +150,8 @@ static int header_identify_match_check(void *obj, void *arg, int flags) c_header = ast_strdupa(identify->match_header); c_value = strchr(c_header, ':'); if (!c_value) { - ast_log(LOG_WARNING, "Identify '%s' has invalid header_match: No ':' separator found!\n", - ast_sorcery_object_get_id(identify)); + /* This should not be possible. The object cannot be created if so. */ + ast_assert(0); return 0; } *c_value = '\0'; @@ -161,17 +161,19 @@ static int header_identify_match_check(void *obj, void *arg, int flags) pj_header_name = pj_str(c_header); header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pj_header_name, NULL); if (!header) { - ast_debug(3, "SIP message does not contain header '%s'\n", c_header); + ast_debug(3, "Identify '%s': SIP message does not have header '%s'\n", + ast_sorcery_object_get_id(identify), + c_header); return 0; } pj_header_value = pj_str(c_value); if (pj_strcmp(&pj_header_value, &header->hvalue)) { - ast_debug(3, "SIP message contains header '%s' but value '%.*s' does not match value '%s' for endpoint '%s'\n", + ast_debug(3, "Identify '%s': SIP message has header '%s' but value '%.*s' does not match '%s'\n", + ast_sorcery_object_get_id(identify), c_header, (int) pj_strlen(&header->hvalue), pj_strbuf(&header->hvalue), - c_value, - identify->endpoint_name); + c_value); return 0; } @@ -261,7 +263,7 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con } for (i = 0; i < num_addrs; ++i) { - /* Check if the address is already in the list, if so don't bother adding it again */ + /* Check if the address is already in the list, if so don't add it again */ if (identify->matches && (ast_apply_ha(identify->matches, &addrs[i]) != AST_SENSE_ALLOW)) { continue; } @@ -283,14 +285,13 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con } /*! \brief Helper function which performs an SRV lookup and then resolves the hostname */ -static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host) +static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host, int results) { char service[NI_MAXHOST]; struct srv_context *context = NULL; int srv_ret; const char *srvhost; unsigned short srvport; - int results = 0; snprintf(service, sizeof(service), "%s.%s", prefix, host); @@ -372,10 +373,33 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj) char *current_string; struct ao2_iterator i; + /* Validate the identify object configuration */ + if (ast_strlen_zero(identify->endpoint_name)) { + ast_log(LOG_ERROR, "Identify '%s' missing required endpoint name.\n", + ast_sorcery_object_get_id(identify)); + return -1; + } + if (ast_strlen_zero(identify->match_header) /* No header to match */ + /* and no static IP addresses with a mask */ + && !identify->matches + /* and no addresses to resolve */ + && (!identify->hosts || !ao2_container_count(identify->hosts))) { + ast_log(LOG_ERROR, "Identify '%s' is not configured to match anything.\n", + ast_sorcery_object_get_id(identify)); + return -1; + } + if (!ast_strlen_zero(identify->match_header) + && !strchr(identify->match_header, ':')) { + ast_log(LOG_ERROR, "Identify '%s' missing ':' separator in match_header '%s'.\n", + ast_sorcery_object_get_id(identify), identify->match_header); + return -1; + } + if (!identify->hosts) { return 0; } + /* Resolve the match addresses now */ i = ao2_iterator_init(identify->hosts, 0); while ((current_string = ao2_iterator_next(&i))) { struct ast_sockaddr address; @@ -383,26 +407,29 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj) /* If the provided string is not an IP address perform SRV resolution on it */ if (identify->srv_lookups && !ast_sockaddr_parse(&address, current_string, 0)) { - results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string); + results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string, + results); if (results != -1) { - results += ip_identify_match_srv_lookup(identify, "_sip._tcp", current_string); + results = ip_identify_match_srv_lookup(identify, "_sip._tcp", + current_string, results); } if (results != -1) { - results += ip_identify_match_srv_lookup(identify, "_sips._tcp", current_string); + results = ip_identify_match_srv_lookup(identify, "_sips._tcp", + current_string, results); } } - /* If SRV falls fall back to a normal lookup on the host itself */ + /* If SRV fails fall back to a normal lookup on the host itself */ if (!results) { results = ip_identify_match_host_lookup(identify, current_string); } if (results == 0) { - ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n", - current_string, ast_sorcery_object_get_id(obj)); + ast_log(LOG_WARNING, "Identify '%s' provided address '%s' did not resolve to any address\n", + ast_sorcery_object_get_id(identify), current_string); } else if (results == -1) { - ast_log(LOG_ERROR, "An error occurred when adding resolution results of '%s' on '%s'\n", - current_string, ast_sorcery_object_get_id(obj)); + ast_log(LOG_ERROR, "Identify '%s' failed when adding resolution results of '%s'\n", + ast_sorcery_object_get_id(identify), current_string); ao2_ref(current_string, -1); ao2_iterator_destroy(&i); return -1; @@ -457,47 +484,54 @@ static int sip_identify_to_ami(const struct ip_identify_match *identify, return ast_sip_sorcery_object_to_ami(identify, buf); } -static int find_identify_by_endpoint(void *obj, void *arg, int flags) +static int send_identify_ami_event(void *obj, void *arg, void *data, int flags) { struct ip_identify_match *identify = obj; const char *endpoint_name = arg; + struct ast_sip_ami *ami = data; + struct ast_str *buf; + + /* Build AMI event */ + buf = ast_sip_create_ami_event("IdentifyDetail", ami); + if (!buf) { + return CMP_STOP; + } + if (sip_identify_to_ami(identify, &buf)) { + ast_free(buf); + return CMP_STOP; + } + ast_str_append(&buf, 0, "EndpointName: %s\r\n", endpoint_name); + + /* Send AMI event */ + astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); + ++ami->count; - return strcmp(identify->endpoint_name, endpoint_name) ? 0 : CMP_MATCH; + ast_free(buf); + return 0; } static int format_ami_endpoint_identify(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami) { - RAII_VAR(struct ao2_container *, identifies, NULL, ao2_cleanup); - RAII_VAR(struct ip_identify_match *, identify, NULL, ao2_cleanup); - RAII_VAR(struct ast_str *, buf, NULL, ast_free); + struct ao2_container *identifies; + struct ast_variable fields = { + .name = "endpoint", + .value = ast_sorcery_object_get_id(endpoint), + }; identifies = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify", - AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + AST_RETRIEVE_FLAG_MULTIPLE, &fields); if (!identifies) { return -1; } - identify = ao2_callback(identifies, 0, find_identify_by_endpoint, - (void *) ast_sorcery_object_get_id(endpoint)); - if (!identify) { - return 1; - } - - if (!(buf = ast_sip_create_ami_event("IdentifyDetail", ami))) { - return -1; - } - - if (sip_identify_to_ami(identify, &buf)) { - return -1; - } - - ast_str_append(&buf, 0, "EndpointName: %s\r\n", - ast_sorcery_object_get_id(endpoint)); - - astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); - ami->count++; + /* Build and send any found identify object's AMI IdentifyDetail event. */ + ao2_callback_data(identifies, OBJ_MULTIPLE | OBJ_NODATA, + send_identify_ami_event, + (void *) ast_sorcery_object_get_id(endpoint), + ami); + ao2_ref(identifies, -1); return 0; } diff --git a/res/res_stasis.c b/res/res_stasis.c index 9a06a5287..5067ca76b 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -500,7 +500,8 @@ static void moh_after_bridge_cb(struct ast_channel *chan, void *data) /*! Request a bridge MOH channel */ static struct ast_channel *prepare_bridge_moh_channel(void) { - RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup); + struct ast_channel *chan; + struct ast_format_cap *cap; cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap) { @@ -509,7 +510,10 @@ static struct ast_channel *prepare_bridge_moh_channel(void) ast_format_cap_append(cap, ast_format_slin, 0); - return ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL); + chan = ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL); + ao2_ref(cap, -1); + + return chan; } /*! Provides the moh channel with a thread so it can actually play its music */ @@ -601,23 +605,27 @@ static struct ast_channel *bridge_moh_create(struct ast_bridge *bridge) struct ast_channel *stasis_app_bridge_moh_channel(struct ast_bridge *bridge) { - RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup); + struct ast_channel *chan; + struct stasis_app_bridge_channel_wrapper *moh_wrapper; - { - SCOPED_AO2LOCK(lock, app_bridges_moh); + ao2_lock(app_bridges_moh); + moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK); + if (!moh_wrapper) { + chan = bridge_moh_create(bridge); + } + ao2_unlock(app_bridges_moh); - moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK); - if (!moh_wrapper) { - return bridge_moh_create(bridge); - } + if (moh_wrapper) { + chan = ast_channel_get_by_name(moh_wrapper->channel_id); + ao2_ref(moh_wrapper, -1); } - return ast_channel_get_by_name(moh_wrapper->channel_id); + return chan; } int stasis_app_bridge_moh_stop(struct ast_bridge *bridge) { - RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup); + struct stasis_app_bridge_channel_wrapper *moh_wrapper; struct ast_channel *chan; moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_UNLINK); @@ -626,6 +634,7 @@ int stasis_app_bridge_moh_stop(struct ast_bridge *bridge) } chan = ast_channel_get_by_name(moh_wrapper->channel_id); + ao2_ref(moh_wrapper, -1); if (!chan) { return -1; } @@ -833,25 +842,30 @@ static const struct ast_datastore_info replace_channel_store_info = { static struct replace_channel_store *get_replace_channel_store(struct ast_channel *chan, int no_create) { struct ast_datastore *datastore; + struct replace_channel_store *ret; - SCOPED_CHANNELLOCK(lock, chan); + ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &replace_channel_store_info, NULL); - if (!datastore) { - if (no_create) { - return NULL; - } - + if (!datastore && !no_create) { datastore = ast_datastore_alloc(&replace_channel_store_info, NULL); - if (!datastore) { - return NULL; + if (datastore) { + ast_channel_datastore_add(chan, datastore); } - ast_channel_datastore_add(chan, datastore); + } + + if (!datastore) { + ast_channel_unlock(chan); + return NULL; } if (!datastore->data) { datastore->data = ast_calloc(1, sizeof(struct replace_channel_store)); } - return datastore->data; + + ret = datastore->data; + ast_channel_unlock(chan); + + return ret; } int app_set_replace_channel_snapshot(struct ast_channel *chan, struct ast_channel_snapshot *replace_snapshot) @@ -930,9 +944,9 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app int argc, char *argv[], struct ast_channel_snapshot *snapshot, struct ast_channel_snapshot *replace_channel_snapshot) { - RAII_VAR(struct ast_json *, json_blob, NULL, ast_json_unref); + struct ast_json *json_blob; struct ast_json *json_args; - RAII_VAR(struct start_message_blob *, payload, NULL, ao2_cleanup); + struct start_message_blob *payload; struct stasis_message *msg; int i; @@ -957,8 +971,11 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app "args"); if (!json_blob) { ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n"); + ao2_ref(payload, -1); return -1; } + payload->blob = json_blob; + /* Append arguments to args array */ json_args = ast_json_object_get(json_blob, "args"); @@ -968,13 +985,14 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app ast_json_string_create(argv[i])); if (r != 0) { ast_log(LOG_ERROR, "Error appending to StasisStart message\n"); + ao2_ref(payload, -1); return -1; } } - payload->blob = ast_json_ref(json_blob); msg = stasis_message_create(start_message_type(), payload); + ao2_ref(payload, -1); if (!msg) { ast_log(LOG_ERROR, "Error sending StasisStart message\n"); return -1; @@ -991,9 +1009,9 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app static int send_start_msg(struct stasis_app *app, struct ast_channel *chan, int argc, char *argv[]) { - RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); - RAII_VAR(struct ast_channel_snapshot *, replace_channel_snapshot, - NULL, ao2_cleanup); + int ret = -1; + struct ast_channel_snapshot *snapshot; + struct ast_channel_snapshot *replace_channel_snapshot; ast_assert(chan != NULL); @@ -1003,10 +1021,13 @@ static int send_start_msg(struct stasis_app *app, struct ast_channel *chan, ast_channel_lock(chan); snapshot = ast_channel_snapshot_create(chan); ast_channel_unlock(chan); - if (!snapshot) { - return -1; + if (snapshot) { + ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot); + ao2_ref(snapshot, -1); } - return send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot); + ao2_cleanup(replace_channel_snapshot); + + return ret; } static void remove_masquerade_store(struct ast_channel *chan); @@ -1449,7 +1470,7 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc, int stasis_app_send(const char *app_name, struct ast_json *message) { - RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup); + struct stasis_app *app; if (!apps_registry) { return -1; @@ -1465,6 +1486,8 @@ int stasis_app_send(const char *app_name, struct ast_json *message) return -1; } app_send(app, message); + ao2_ref(app, -1); + return 0; } @@ -1499,7 +1522,7 @@ static int append_name(void *obj, void *arg, int flags) struct ao2_container *stasis_app_get_all(void) { - RAII_VAR(struct ao2_container *, apps, NULL, ao2_cleanup); + struct ao2_container *apps; if (!apps_registry) { return NULL; @@ -1512,12 +1535,12 @@ struct ao2_container *stasis_app_get_all(void) ao2_callback(apps_registry, OBJ_NODATA, append_name, apps); - return ao2_bump(apps); + return apps; } static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events) { - RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup); + struct stasis_app *app; if (!apps_registry) { return -1; @@ -1529,24 +1552,25 @@ static int __stasis_app_register(const char *app_name, stasis_app_cb handler, vo app_update(app, handler, data); } else { app = app_create(app_name, handler, data, all_events ? STASIS_APP_SUBSCRIBE_ALL : STASIS_APP_SUBSCRIBE_MANUAL); - if (app) { - if (all_events) { - struct stasis_app_event_source *source; - SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK); + if (!app) { + ao2_unlock(apps_registry); + return -1; + } - AST_LIST_TRAVERSE(&event_sources, source, next) { - if (!source->subscribe) { - continue; - } + if (all_events) { + struct stasis_app_event_source *source; - source->subscribe(app, NULL); + AST_RWLIST_RDLOCK(&event_sources); + AST_LIST_TRAVERSE(&event_sources, source, next) { + if (!source->subscribe) { + continue; } + + source->subscribe(app, NULL); } - ao2_link_flags(apps_registry, app, OBJ_NOLOCK); - } else { - ao2_unlock(apps_registry); - return -1; + AST_RWLIST_UNLOCK(&event_sources); } + ao2_link_flags(apps_registry, app, OBJ_NOLOCK); } /* We lazily clean up the apps_registry, because it's good enough to @@ -1554,6 +1578,7 @@ static int __stasis_app_register(const char *app_name, stasis_app_cb handler, vo */ cleanup(); ao2_unlock(apps_registry); + ao2_ref(app, -1); return 0; } @@ -1569,7 +1594,7 @@ int stasis_app_register_all(const char *app_name, stasis_app_cb handler, void *d void stasis_app_unregister(const char *app_name) { - RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup); + struct stasis_app *app; if (!app_name) { return; @@ -1592,23 +1617,27 @@ void stasis_app_unregister(const char *app_name) * and clean up, just in case */ cleanup(); + + ao2_ref(app, -1); } void stasis_app_register_event_source(struct stasis_app_event_source *obj) { - SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK); + AST_RWLIST_WRLOCK(&event_sources); AST_LIST_INSERT_TAIL(&event_sources, obj, next); /* only need to bump the module ref on non-core sources because the core ones are [un]registered by this module. */ if (!stasis_app_is_core_event_source(obj)) { ast_module_ref(ast_module_info->self); } + AST_RWLIST_UNLOCK(&event_sources); } void stasis_app_unregister_event_source(struct stasis_app_event_source *obj) { struct stasis_app_event_source *source; - SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK); + + AST_RWLIST_WRLOCK(&event_sources); AST_RWLIST_TRAVERSE_SAFE_BEGIN(&event_sources, source, next) { if (source == obj) { AST_RWLIST_REMOVE_CURRENT(next); @@ -1619,6 +1648,7 @@ void stasis_app_unregister_event_source(struct stasis_app_event_source *obj) } } AST_RWLIST_TRAVERSE_SAFE_END; + AST_RWLIST_UNLOCK(&event_sources); } /*! @@ -1637,12 +1667,15 @@ static struct ast_json *app_event_sources_to_json( const struct stasis_app *app, struct ast_json *json) { struct stasis_app_event_source *source; - SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK); + + AST_RWLIST_RDLOCK(&event_sources); AST_LIST_TRAVERSE(&event_sources, source, next) { if (source->to_json) { source->to_json(app, json); } } + AST_RWLIST_UNLOCK(&event_sources); + return json; } @@ -1657,9 +1690,12 @@ static struct ast_json *stasis_app_object_to_json(struct stasis_app *app) struct ast_json *stasis_app_to_json(const char *app_name) { - RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup); + struct stasis_app *app = find_app_by_name(app_name); + struct ast_json *json = stasis_app_object_to_json(app); - return stasis_app_object_to_json(app); + ao2_cleanup(app); + + return json; } /*! @@ -1676,13 +1712,16 @@ struct ast_json *stasis_app_to_json(const char *app_name) static struct stasis_app_event_source *app_event_source_find(const char *uri) { struct stasis_app_event_source *source; - SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK); + + AST_RWLIST_RDLOCK(&event_sources); AST_LIST_TRAVERSE(&event_sources, source, next) { if (ast_begins_with(uri, source->scheme)) { - return source; + break; } } - return NULL; + AST_RWLIST_UNLOCK(&event_sources); + + return source; } /*! @@ -1717,25 +1756,32 @@ static enum stasis_app_subscribe_res app_handle_subscriptions( int event_sources_count, struct ast_json **json, app_subscription_handler handler) { - RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup); + struct stasis_app *app = find_app_by_name(app_name); int i; + ast_assert(handler != NULL); + if (!app) { return STASIS_ASR_APP_NOT_FOUND; } for (i = 0; i < event_sources_count; ++i) { const char *uri = event_source_uris[i]; - enum stasis_app_subscribe_res res = STASIS_ASR_INTERNAL_ERROR; struct stasis_app_event_source *event_source; + enum stasis_app_subscribe_res res; - if (!(event_source = app_event_source_find(uri))) { + event_source = app_event_source_find(uri); + if (!event_source) { ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri); + ao2_ref(app, -1); + return STASIS_ASR_EVENT_SOURCE_BAD_SCHEME; } - if (handler && - ((res = handler(app, uri, event_source)))) { + res = handler(app, uri, event_source); + if (res != STASIS_ASR_OK) { + ao2_ref(app, -1); + return res; } } @@ -1745,13 +1791,15 @@ static enum stasis_app_subscribe_res app_handle_subscriptions( *json = stasis_app_object_to_json(app); } + ao2_ref(app, -1); + return STASIS_ASR_OK; } enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name, struct ast_channel *chan) { - RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup); + struct stasis_app *app = find_app_by_name(app_name); int res; if (!app) { @@ -1761,6 +1809,8 @@ enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name, ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan)); res = app_subscribe_channel(app, chan); + ao2_ref(app, -1); + if (res != 0) { ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n", app_name, ast_channel_uniqueid(chan)); @@ -1863,12 +1913,10 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name, struct ast_json *json_variables) { RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup); - RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); - RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup); - RAII_VAR(void *, obj, NULL, ao2_cleanup); - RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + struct ast_json *blob = NULL; + struct ast_multi_object_blob *multi; + struct stasis_message *message; enum stasis_app_user_event_res res = STASIS_APP_USER_INTERNAL_ERROR; - struct ast_json *json_value; int have_channel = 0; int i; @@ -1881,23 +1929,29 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name, return res; } - blob = json_variables; - if (!blob) { - blob = ast_json_pack("{}"); + if (json_variables) { + struct ast_json *json_value = ast_json_string_create(event_name); + + if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) { + blob = ast_json_ref(json_variables); + } } else { - ast_json_ref(blob); + blob = ast_json_pack("{s: s}", "eventname", event_name); } - json_value = ast_json_string_create(event_name); - if (!json_value) { - ast_log(LOG_ERROR, "unable to create json string\n"); - return res; - } - if (ast_json_object_set(blob, "eventname", json_value)) { - ast_log(LOG_ERROR, "unable to set eventname to blob\n"); + + if (!blob) { + ast_log(LOG_ERROR, "Failed to initialize blob\n"); + return res; } multi = ast_multi_object_blob_create(blob); + ast_json_unref(blob); + if (!multi) { + ast_log(LOG_ERROR, "Failed to initialize multi\n"); + + return res; + } for (i = 0; i < sources_count; ++i) { const char *uri = source_uris[i]; @@ -1916,16 +1970,22 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name, snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL); } else { ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri); + ao2_ref(multi, -1); + return STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME; } if (!snapshot) { ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri); + ao2_ref(multi, -1); + return STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND; } ast_multi_object_blob_add(multi, type, snapshot); } message = stasis_message_create(ast_multi_user_event_type(), multi); + ao2_ref(multi, -1); + if (!message) { ast_log(LOG_ERROR, "Unable to create stasis user event message\n"); return res; @@ -1942,6 +2002,7 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name, if (have_channel) { stasis_publish(ast_manager_get_topic(), message); } + ao2_ref(message, -1); return STASIS_APP_USER_OK; } @@ -2005,9 +2066,14 @@ static int channel_sanitizer(const struct ast_channel *chan) /* \brief Sanitization callback for channel unique IDs */ static int channel_id_sanitizer(const char *id) { - RAII_VAR(struct ast_channel_snapshot *, snapshot, ast_channel_snapshot_get_latest(id), ao2_cleanup); + struct ast_channel_snapshot *snapshot; + int ret; + + snapshot = ast_channel_snapshot_get_latest(id); + ret = channel_snapshot_sanitizer(snapshot); + ao2_cleanup(snapshot); - return channel_snapshot_sanitizer(snapshot); + return ret; } /* \brief Sanitization callbacks for communication to Stasis applications */ diff --git a/res/stasis/app.c b/res/stasis/app.c index 91b006572..ccb93bc4d 100644 --- a/res/stasis/app.c +++ b/res/stasis/app.c @@ -114,20 +114,19 @@ static void forwards_unsubscribe(struct app_forwards *forwards) static struct app_forwards *forwards_create(struct stasis_app *app, const char *id) { - RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup); + struct app_forwards *forwards; if (!app || ast_strlen_zero(id)) { return NULL; } - forwards = ao2_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor); + forwards = ao2_t_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor, id); if (!forwards) { return NULL; } - strcpy(forwards->id, id); + strcpy(forwards->id, id); /* SAFE */ - ao2_ref(forwards, +1); return forwards; } @@ -338,7 +337,7 @@ static void sub_default_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct stasis_app *app = data; - RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + struct ast_json *json; if (stasis_subscription_final_message(sub, message)) { ao2_cleanup(app); @@ -355,6 +354,7 @@ static void sub_default_handler(void *data, struct stasis_subscription *sub, } app_send(app, json); + ast_json_unref(json); } /*! \brief Typedef for callbacks that get called on channel snapshot updates */ @@ -557,11 +557,12 @@ static void sub_channel_update_handler(void *data, stasis_message_timestamp(message); for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) { - RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); + struct ast_json *msg; msg = channel_monitors[i](old_snapshot, new_snapshot, tv); if (msg) { app_send(app, msg); + ast_json_unref(msg); } } @@ -589,7 +590,7 @@ static struct ast_json *simple_endpoint_event( static int message_received_handler(const char *endpoint_id, struct ast_json *json_msg, void *pvt) { - RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup); + struct ast_endpoint_snapshot *snapshot; struct ast_json *json_endpoint; struct ast_json *message; struct stasis_app *app = pvt; @@ -613,6 +614,7 @@ static int message_received_handler(const char *endpoint_id, struct ast_json *js } json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer()); + ao2_ref(snapshot, -1); if (!json_endpoint) { return -1; } @@ -634,7 +636,6 @@ static void sub_endpoint_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { - RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); struct stasis_app *app = data; struct stasis_cache_update *update; struct ast_endpoint_snapshot *new_snapshot; @@ -651,6 +652,8 @@ static void sub_endpoint_update_handler(void *data, old_snapshot = stasis_message_data(update->old_snapshot); if (new_snapshot) { + struct ast_json *json; + tv = stasis_message_timestamp(update->new_snapshot); json = simple_endpoint_event("EndpointStateChange", new_snapshot, tv); @@ -659,6 +662,7 @@ static void sub_endpoint_update_handler(void *data, } app_send(app, json); + ast_json_unref(json); } if (!new_snapshot && old_snapshot) { @@ -686,7 +690,7 @@ static void sub_bridge_update_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { - RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + struct ast_json *json = NULL; struct stasis_app *app = data; struct stasis_cache_update *update; struct ast_bridge_snapshot *new_snapshot; @@ -720,6 +724,7 @@ static void sub_bridge_update_handler(void *data, if (json) { app_send(app, json); + ast_json_unref(json); } if (!new_snapshot && old_snapshot) { @@ -1022,7 +1027,7 @@ void app_send(struct stasis_app *app, struct ast_json *message) { stasis_app_cb handler; char eid[20]; - RAII_VAR(void *, data, NULL, ao2_cleanup); + void *data; if (ast_json_object_set(message, "asterisk_id", ast_json_string_create( ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) { @@ -1031,37 +1036,36 @@ void app_send(struct stasis_app *app, struct ast_json *message) } /* Copy off mutable state with lock held */ - { - SCOPED_AO2LOCK(lock, app); - handler = app->handler; - if (app->data) { - ao2_ref(app->data, +1); - data = app->data; - } - /* Name is immutable; no need to copy */ - } - - if (!handler) { + ao2_lock(app); + handler = app->handler; + data = ao2_bump(app->data); + ao2_unlock(app); + /* Name is immutable; no need to copy */ + + if (handler) { + handler(data, app->name, message); + } else { ast_verb(3, "Inactive Stasis app '%s' missed message\n", app->name); - return; } - - handler(data, app->name, message); + ao2_cleanup(data); } void app_deactivate(struct stasis_app *app) { - SCOPED_AO2LOCK(lock, app); + ao2_lock(app); + ast_verb(1, "Deactivating Stasis app '%s'\n", app->name); app->handler = NULL; ao2_cleanup(app->data); app->data = NULL; + + ao2_unlock(app); } void app_shutdown(struct stasis_app *app) { - SCOPED_AO2LOCK(lock, app); + ao2_lock(app); ast_assert(app_is_finished(app)); @@ -1071,27 +1075,37 @@ void app_shutdown(struct stasis_app *app) app->bridge_router = NULL; stasis_message_router_unsubscribe(app->endpoint_router); app->endpoint_router = NULL; + + ao2_unlock(app); } int app_is_active(struct stasis_app *app) { - SCOPED_AO2LOCK(lock, app); - return app->handler != NULL; + int ret; + + ao2_lock(app); + ret = app->handler != NULL; + ao2_unlock(app); + + return ret; } int app_is_finished(struct stasis_app *app) { - SCOPED_AO2LOCK(lock, app); + int ret; + + ao2_lock(app); + ret = app->handler == NULL && ao2_container_count(app->forwards) == 0; + ao2_unlock(app); - return app->handler == NULL && ao2_container_count(app->forwards) == 0; + return ret; } void app_update(struct stasis_app *app, stasis_app_cb handler, void *data) { - SCOPED_AO2LOCK(lock, app); - + ao2_lock(app); if (app->handler && app->data) { - RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); + struct ast_json *msg; ast_verb(1, "Replacing Stasis app '%s'\n", app->name); @@ -1100,17 +1114,15 @@ void app_update(struct stasis_app *app, stasis_app_cb handler, void *data) "application", app->name); if (msg) { app_send(app, msg); + ast_json_unref(msg); } } else { ast_verb(1, "Activating Stasis app '%s'\n", app->name); } app->handler = handler; - ao2_cleanup(app->data); - if (data) { - ao2_ref(data, +1); - } - app->data = data; + ao2_replace(app->data, data); + ao2_unlock(app); } const char *stasis_app_name(const struct stasis_app *app) @@ -1187,68 +1199,72 @@ void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a) struct ast_json *app_to_json(const struct stasis_app *app) { - RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + struct ast_json *json; struct ast_json *channels; struct ast_json *bridges; struct ast_json *endpoints; struct ao2_iterator i; - void *obj; + struct app_forwards *forwards; json = ast_json_pack("{s: s, s: [], s: [], s: []}", "name", app->name, "channel_ids", "bridge_ids", "endpoint_ids"); + if (!json) { + return NULL; + } channels = ast_json_object_get(json, "channel_ids"); bridges = ast_json_object_get(json, "bridge_ids"); endpoints = ast_json_object_get(json, "endpoint_ids"); i = ao2_iterator_init(app->forwards, 0); - while ((obj = ao2_iterator_next(&i))) { - RAII_VAR(struct app_forwards *, forwards, obj, ao2_cleanup); - RAII_VAR(struct ast_json *, id, NULL, ast_json_unref); - int append_res = -1; - - id = ast_json_string_create(forwards->id); + while ((forwards = ao2_iterator_next(&i))) { + struct ast_json *array = NULL; + int append_res; switch (forwards->forward_type) { case FORWARD_CHANNEL: - append_res = ast_json_array_append(channels, - ast_json_ref(id)); + array = channels; break; case FORWARD_BRIDGE: - append_res = ast_json_array_append(bridges, - ast_json_ref(id)); + array = bridges; break; case FORWARD_ENDPOINT: - append_res = ast_json_array_append(endpoints, - ast_json_ref(id)); + array = endpoints; break; } + /* If forward_type value is unexpected this will safely return an error. */ + append_res = ast_json_array_append(array, ast_json_string_create(forwards->id)); + ao2_ref(forwards, -1); + if (append_res != 0) { ast_log(LOG_ERROR, "Error building response\n"); ao2_iterator_destroy(&i); + ast_json_unref(json); + return NULL; } } ao2_iterator_destroy(&i); - return ast_json_ref(json); + return json; } int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan) { struct app_forwards *forwards; - SCOPED_AO2LOCK(lock, app->forwards); - int res; if (!app) { return -1; } + ao2_lock(app->forwards); /* If subscribed to all, don't subscribe again */ forwards = ao2_find(app->forwards, CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (forwards) { + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } @@ -1256,16 +1272,21 @@ int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan) chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (!forwards) { + int res; + /* Forwards not found, create one */ forwards = forwards_create_channel(app, chan); if (!forwards) { + ao2_unlock(app->forwards); + return -1; } - res = ao2_link_flags(app->forwards, forwards, - OBJ_NOLOCK); + res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK); if (!res) { + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return -1; } } @@ -1276,7 +1297,9 @@ int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan) forwards->interested, app->name); + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } @@ -1287,8 +1310,7 @@ static int subscribe_channel(struct stasis_app *app, void *obj) static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate) { - RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup); - SCOPED_AO2LOCK(lock, app->forwards); + struct app_forwards *forwards; if (!id) { if (!strcmp(kind, "bridge")) { @@ -1303,8 +1325,10 @@ static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, } } + ao2_lock(app->forwards); forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (!forwards) { + ao2_unlock(app->forwards); ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id); return -1; } @@ -1323,6 +1347,8 @@ static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, messaging_app_unsubscribe_endpoint(app->name, id); } } + ao2_unlock(app->forwards); + ao2_ref(forwards, -1); return 0; } @@ -1347,12 +1373,14 @@ int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id) int app_is_subscribed_channel_id(struct stasis_app *app, const char *channel_id) { - RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup); + struct app_forwards *forwards; if (ast_strlen_zero(channel_id)) { channel_id = CHANNEL_ALL; } forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY); + ao2_cleanup(forwards); + return forwards != NULL; } @@ -1372,28 +1400,42 @@ struct stasis_app_event_source channel_event_source = { int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge) { struct app_forwards *forwards; - SCOPED_AO2LOCK(lock, app->forwards); if (!app) { return -1; } + ao2_lock(app->forwards); /* If subscribed to all, don't subscribe again */ forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (forwards) { + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } - forwards = ao2_find(app->forwards, bridge ? bridge->uniqueid : BRIDGE_ALL, + forwards = ao2_find(app->forwards, + bridge ? bridge->uniqueid : BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (!forwards) { + int res; + /* Forwards not found, create one */ forwards = forwards_create_bridge(app, bridge); if (!forwards) { + ao2_unlock(app->forwards); + + return -1; + } + + res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK); + if (!res) { + ao2_unlock(app->forwards); + ao2_ref(forwards, -1); + return -1; } - ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK); } ++forwards->interested; @@ -1402,7 +1444,9 @@ int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge) forwards->interested, app->name); + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } @@ -1459,16 +1503,18 @@ struct stasis_app_event_source bridge_event_source = { int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint) { struct app_forwards *forwards; - SCOPED_AO2LOCK(lock, app->forwards); if (!app) { return -1; } + ao2_lock(app->forwards); /* If subscribed to all, don't subscribe again */ forwards = ao2_find(app->forwards, ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (forwards) { + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } @@ -1476,12 +1522,23 @@ int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (!forwards) { + int res; + /* Forwards not found, create one */ forwards = forwards_create_endpoint(app, endpoint); if (!forwards) { + ao2_unlock(app->forwards); + + return -1; + } + + res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK); + if (!res) { + ao2_unlock(app->forwards); + ao2_ref(forwards, -1); + return -1; } - ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK); /* Subscribe for messages */ messaging_app_subscribe_endpoint(app->name, endpoint, &message_received_handler, app); @@ -1493,7 +1550,9 @@ int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint forwards->interested, app->name); + ao2_unlock(app->forwards); ao2_ref(forwards, -1); + return 0; } @@ -1513,12 +1572,14 @@ int app_unsubscribe_endpoint_id(struct stasis_app *app, const char *endpoint_id) int app_is_subscribed_endpoint_id(struct stasis_app *app, const char *endpoint_id) { - RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup); + struct app_forwards *forwards; if (ast_strlen_zero(endpoint_id)) { endpoint_id = ENDPOINT_ALL; } forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY); + ao2_cleanup(forwards); + return forwards != NULL; } diff --git a/res/stasis/command.c b/res/stasis/command.c index 534e434ec..024f02b6a 100644 --- a/res/stasis/command.c +++ b/res/stasis/command.c @@ -78,21 +78,26 @@ struct stasis_app_command *command_create( void command_complete(struct stasis_app_command *command, int retval) { - SCOPED_MUTEX(lock, &command->lock); - + ast_mutex_lock(&command->lock); command->is_done = 1; command->retval = retval; ast_cond_signal(&command->condition); + ast_mutex_unlock(&command->lock); } int command_join(struct stasis_app_command *command) { - SCOPED_MUTEX(lock, &command->lock); + int ret; + + ast_mutex_lock(&command->lock); while (!command->is_done) { ast_cond_wait(&command->condition, &command->lock); } - return command->retval; + ret = command->retval; + ast_mutex_unlock(&command->lock); + + return ret; } void command_invoke(struct stasis_app_command *command, diff --git a/res/stasis/control.c b/res/stasis/control.c index 7e8ea91ef..df97931a7 100644 --- a/res/stasis/control.c +++ b/res/stasis/control.c @@ -137,8 +137,9 @@ static void app_control_register_rule( const struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj) { - SCOPED_AO2LOCK(lock, control->command_queue); + ao2_lock(control->command_queue); AST_LIST_INSERT_TAIL(list, obj, next); + ao2_unlock(control->command_queue); } static void app_control_unregister_rule( @@ -146,7 +147,8 @@ static void app_control_unregister_rule( struct app_control_rules *list, struct stasis_app_control_rule *obj) { struct stasis_app_control_rule *rule; - SCOPED_AO2LOCK(lock, control->command_queue); + + ao2_lock(control->command_queue); AST_RWLIST_TRAVERSE_SAFE_BEGIN(list, rule, next) { if (rule == obj) { AST_RWLIST_REMOVE_CURRENT(next); @@ -154,6 +156,7 @@ static void app_control_unregister_rule( } } AST_RWLIST_TRAVERSE_SAFE_END; + ao2_unlock(control->command_queue); } /*! @@ -580,9 +583,10 @@ static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data) { struct stasis_app_control_mute_data *mute_data = data; - SCOPED_CHANNELLOCK(lockvar, chan); + ast_channel_lock(chan); ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype); + ast_channel_unlock(chan); return 0; } @@ -607,9 +611,10 @@ static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data) { struct stasis_app_control_mute_data *mute_data = data; - SCOPED_CHANNELLOCK(lockvar, chan); + ast_channel_lock(chan); ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype); + ast_channel_unlock(chan); return 0; } @@ -818,7 +823,7 @@ void stasis_app_control_silence_stop(struct stasis_app_control *control) struct ast_channel_snapshot *stasis_app_control_get_snapshot( const struct stasis_app_control *control) { - RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); + struct stasis_message *msg; struct ast_channel_snapshot *snapshot; msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(), @@ -831,6 +836,8 @@ struct ast_channel_snapshot *stasis_app_control_get_snapshot( ast_assert(snapshot != NULL); ao2_ref(snapshot, +1); + ao2_ref(msg, -1); + return snapshot; } @@ -839,7 +846,8 @@ static int app_send_command_on_condition(struct stasis_app_control *control, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn) { - RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup); + int ret; + struct stasis_app_command *command; if (control == NULL || control->is_done) { /* If exec_command_on_condition fails, it calls the data_destructor. @@ -859,7 +867,10 @@ static int app_send_command_on_condition(struct stasis_app_control *control, return -1; } - return command_join(command); + ret = command_join(command); + ao2_ref(command, -1); + + return ret; } int stasis_app_send_command(struct stasis_app_control *control, @@ -872,7 +883,7 @@ int stasis_app_send_command_async(struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor) { - RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup); + struct stasis_app_command *command; if (control == NULL || control->is_done) { /* If exec_command fails, it calls the data_destructor. In order to @@ -890,33 +901,39 @@ int stasis_app_send_command_async(struct stasis_app_control *control, if (!command) { return -1; } + ao2_ref(command, -1); return 0; } struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control) { + struct ast_bridge *ret; + if (!control) { return NULL; - } else { - SCOPED_AO2LOCK(lock, control); - return control->bridge; } + + ao2_lock(control); + ret = control->bridge; + ao2_unlock(control); + + return ret; } static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data) { - struct ast_bridge_channel *bridge_channel = data; + struct ast_bridge_channel *bridge_channel; - { - SCOPED_CHANNELLOCK(lock, chan); + ast_channel_lock(chan); + bridge_channel = ast_channel_internal_bridge_channel(chan); + ast_channel_unlock(chan); - if (bridge_channel != ast_channel_internal_bridge_channel(chan)) { - ast_debug(3, "%s: Channel is no longer in departable state\n", - ast_channel_uniqueid(chan)); - return -1; - } + if (bridge_channel != data) { + ast_debug(3, "%s: Channel is no longer in departable state\n", + ast_channel_uniqueid(chan)); + return -1; } ast_debug(3, "%s: Channel departing bridge\n", @@ -931,9 +948,9 @@ static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason) { struct stasis_app_control *control = data; - SCOPED_AO2LOCK(lock, control); struct ast_bridge_channel *bridge_channel; + ao2_lock(control); ast_debug(3, "%s, %s: %s\n", ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown", ast_bridge_after_cb_reason_string(reason)); @@ -979,6 +996,7 @@ static void internal_bridge_after_cb(struct ast_channel *chan, void *data, ast_softhangup_nolock(chan, hangup_flag); ast_channel_unlock(chan); } + ao2_unlock(control); } static void bridge_after_cb(struct ast_channel *chan, void *data) diff --git a/res/stasis/stasis_bridge.c b/res/stasis/stasis_bridge.c index 81b35e308..701cbaea8 100644 --- a/res/stasis/stasis_bridge.c +++ b/res/stasis/stasis_bridge.c @@ -252,7 +252,7 @@ static int bridge_stasis_moving(struct ast_bridge_channel *bridge_channel, void { if (src->v_table == &bridge_stasis_v_table && dst->v_table != &bridge_stasis_v_table) { - RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + struct stasis_app_control *control; struct ast_channel *chan; chan = bridge_channel->chan; @@ -265,6 +265,7 @@ static int bridge_stasis_moving(struct ast_bridge_channel *bridge_channel, void stasis_app_channel_set_stasis_end_published(chan); app_send_end_msg(control_app(control), chan); + ao2_ref(control, -1); } return -1; |