[asterisk-commits] jrose: branch jrose/bridge_projects r385308 - in /team/jrose/bridge_projects:...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Apr 11 09:55:55 CDT 2013
Author: jrose
Date: Thu Apr 11 09:55:51 2013
New Revision: 385308
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385308
Log:
resolve conflict, enable automerge
Modified:
team/jrose/bridge_projects/ (props changed)
team/jrose/bridge_projects/apps/app_confbridge.c
team/jrose/bridge_projects/main/bridging.c
team/jrose/bridge_projects/main/features.c
team/jrose/bridge_projects/main/manager.c
Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
automerge = *
Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Thu Apr 11 09:55:51 2013
@@ -1,1 +1,1 @@
-/trunk:1-385237
+/trunk:1-385278
Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_projects-integrated (original)
+++ bridge_projects-integrated Thu Apr 11 09:55:51 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-385272
+/team/group/bridge_construction:1-385307
Modified: team/jrose/bridge_projects/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/apps/app_confbridge.c?view=diff&rev=385308&r1=385307&r2=385308
==============================================================================
--- team/jrose/bridge_projects/apps/app_confbridge.c (original)
+++ team/jrose/bridge_projects/apps/app_confbridge.c Thu Apr 11 09:55:51 2013
@@ -649,6 +649,7 @@
struct ast_channel *chan;
struct ast_str *filename = ast_str_alloca(PATH_MAX);
struct ast_str *orig_rec_file = NULL;
+ struct ast_bridge_features features;
ast_mutex_lock(&conference->record_lock);
if (!mixmonapp) {
@@ -658,20 +659,27 @@
ao2_ref(conference, -1);
return NULL;
}
+ if (ast_bridge_features_init(&features)) {
+ conference->record_thread = AST_PTHREADT_NULL;
+ ast_mutex_unlock(&conference->record_lock);
+ ao2_ref(conference, -1);
+ return NULL;
+ }
/* XXX If we get an EXIT right here, START will essentially be a no-op */
while (conference->record_state != CONF_RECORD_EXIT) {
set_rec_filename(conference, &filename,
- is_new_rec_file(conference->b_profile.rec_file, &orig_rec_file));
+ is_new_rec_file(conference->b_profile.rec_file, &orig_rec_file));
chan = ast_channel_ref(conference->record_chan);
ast_answer(chan);
pbx_exec(chan, mixmonapp, ast_str_buffer(filename));
- ast_bridge_join(conference->bridge, chan, NULL, NULL, NULL, 0);
+ ast_bridge_join(conference->bridge, chan, NULL, &features, NULL, 0);
ast_hangup(chan); /* This will eat this thread's reference to the channel as well */
/* STOP has been called. Wait for either a START or an EXIT */
ast_cond_wait(&conference->record_cond, &conference->record_lock);
}
+ ast_bridge_features_cleanup(&features);
ast_free(orig_rec_file);
ast_mutex_unlock(&conference->record_lock);
ao2_ref(conference, -1);
Modified: team/jrose/bridge_projects/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/bridging.c?view=diff&rev=385308&r1=385307&r2=385308
==============================================================================
--- team/jrose/bridge_projects/main/bridging.c (original)
+++ team/jrose/bridge_projects/main/bridging.c Thu Apr 11 09:55:51 2013
@@ -572,6 +572,7 @@
}
/* BUGBUG the feature hook matching needs to be done here. Any matching feature hook needs to be queued onto the bridge_channel. Also the feature hook digit timeout needs to be handled. */
+/* BUGBUG the AMI atxfer action just sends DTMF end events to initiate DTMF atxfer and dial the extension. Another reason the DTMF hook matching needs rework. */
/* See if this DTMF matches the beginnings of any feature hooks, if so we switch to the feature state to either execute the feature or collect more DTMF */
dtmf[0] = frame->subclass.integer;
dtmf[1] = '\0';
@@ -689,8 +690,10 @@
bridge_channel_write_frame(bridge_channel, &frame);
}
-static void run_app_helper(struct ast_channel *chan, const char *app_name, const char *app_args)
-{
+static int run_app_helper(struct ast_channel *chan, const char *app_name, const char *app_args)
+{
+ int res = 0;
+
if (!strcasecmp("Gosub", app_name)) {
ast_app_exec_sub(NULL, chan, app_args, 0);
} else if (!strcasecmp("Macro", app_name)) {
@@ -702,9 +705,10 @@
if (!app) {
ast_log(LOG_WARNING, "Could not find application (%s)\n", app_name);
} else {
- pbx_exec(chan, app, app_args);
- }
- }
+ res = pbx_exec(chan, app, app_args);
+ }
+ }
+ return res;
}
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
@@ -718,7 +722,10 @@
moh_class, strlen(moh_class) + 1);
}
}
- run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""));
+ if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
+ /* Break the bridge if the app returns non-zero. */
+ bridge_handle_hangup(bridge_channel);
+ }
if (moh_class) {
ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD,
NULL, 0);
@@ -726,7 +733,7 @@
}
struct bridge_run_app {
- /*! Offset into app_name[] where the MOH class name starts. (zero if no MOH)*/
+ /*! Offset into app_name[] where the MOH class name starts. (zero if no MOH) */
int moh_offset;
/*! Offset into app_name[] where the application argument string starts. (zero if no arguments) */
int app_args_offset;
@@ -2767,6 +2774,13 @@
state = AST_BRIDGE_CHANNEL_STATE_HANGUP;
goto join_exit;
}
+/* BUGBUG features cannot be NULL when passed in. When it is changed to allocated we can do like ast_bridge_impart() and allocate one. */
+ ast_assert(features != NULL);
+ if (!features) {
+ ao2_ref(bridge_channel, -1);
+ state = AST_BRIDGE_CHANNEL_STATE_HANGUP;
+ goto join_exit;
+ }
if (tech_args) {
bridge_channel->tech_args = *tech_args;
}
@@ -2869,9 +2883,18 @@
int res;
struct ast_bridge_channel *bridge_channel;
+ /* Supply an empty features structure if the caller did not. */
+ if (!features) {
+ features = ast_bridge_features_new();
+ if (!features) {
+ return -1;
+ }
+ }
+
/* Try to allocate a structure for the bridge channel */
bridge_channel = bridge_channel_alloc(bridge);
if (!bridge_channel) {
+ ast_bridge_features_destroy(features);
return -1;
}
Modified: team/jrose/bridge_projects/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/features.c?view=diff&rev=385308&r1=385307&r2=385308
==============================================================================
--- team/jrose/bridge_projects/main/features.c (original)
+++ team/jrose/bridge_projects/main/features.c Thu Apr 11 09:55:51 2013
@@ -747,17 +747,9 @@
return df_copy;
}
-static void dial_features_destroy(void *data)
-{
- struct ast_dial_features *df = data;
- if (df) {
- ast_free(df);
- }
-}
-
static const struct ast_datastore_info dial_features_info = {
.type = "dial-features",
- .destroy = dial_features_destroy,
+ .destroy = ast_free_ptr,
.duplicate = dial_features_duplicate,
};
@@ -2942,6 +2934,25 @@
AST_RWLOCK_DEFINE_STATIC(features_lock);
+/*! \note This is protected by features_lock. */
+static AST_LIST_HEAD_NOLOCK_STATIC(feature_list, ast_call_feature);
+
+static void ast_wrlock_call_features(void)
+{
+ ast_rwlock_wrlock(&features_lock);
+}
+
+void ast_rdlock_call_features(void)
+{
+ ast_rwlock_rdlock(&features_lock);
+}
+
+void ast_unlock_call_features(void)
+{
+ ast_rwlock_unlock(&features_lock);
+}
+
+/*! \note This is protected by features_lock. */
static struct ast_call_feature builtin_features[] = {
{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
@@ -2951,10 +2962,7 @@
{ AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
};
-
-static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
-
-/*! \brief register new feature into feature_list*/
+/*! \brief register new feature into feature_list */
void ast_register_feature(struct ast_call_feature *feature)
{
if (!feature) {
@@ -2962,9 +2970,9 @@
return;
}
- AST_RWLIST_WRLOCK(&feature_list);
- AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_wrlock_call_features();
+ AST_LIST_INSERT_HEAD(&feature_list, feature, feature_entry);
+ ast_unlock_call_features();
ast_verb(2, "Registered Feature '%s'\n",feature->sname);
}
@@ -3041,9 +3049,9 @@
return;
}
- AST_RWLIST_WRLOCK(&feature_list);
- AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_wrlock_call_features();
+ AST_LIST_REMOVE(&feature_list, feature, feature_entry);
+ ast_unlock_call_features();
ast_free(feature);
}
@@ -3053,19 +3061,23 @@
{
struct ast_call_feature *feature;
- AST_RWLIST_WRLOCK(&feature_list);
- while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
+ ast_wrlock_call_features();
+ while ((feature = AST_LIST_REMOVE_HEAD(&feature_list, feature_entry))) {
ast_free(feature);
}
- AST_RWLIST_UNLOCK(&feature_list);
-}
-
-/*! \brief find a call feature by name */
+ ast_unlock_call_features();
+}
+
+/*!
+ * \internal
+ * \brief find a dynamic call feature by name
+ * \pre Expects features_lock to be at least readlocked
+ */
static struct ast_call_feature *find_dynamic_feature(const char *name)
{
struct ast_call_feature *tmp;
- AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
+ AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
if (!strcasecmp(tmp->sname, name)) {
break;
}
@@ -3111,19 +3123,9 @@
return fg;
}
-void ast_rdlock_call_features(void)
-{
- ast_rwlock_rdlock(&features_lock);
-}
-
-void ast_unlock_call_features(void)
-{
- ast_rwlock_unlock(&features_lock);
-}
-
/*!
* \internal
- * \pre Expects feature_lock to be readlocked
+ * \pre Expects features_lock to be at least readlocked
*/
struct ast_call_feature *ast_find_call_feature(const char *name)
{
@@ -3269,7 +3271,7 @@
* \internal
* \brief Get the extension for a given builtin feature
*
- * \pre expects feature_lock to be readlocked
+ * \pre expects features_lock to be readlocked
*
* \retval 0 success
* \retval non-zero failiure
@@ -3386,17 +3388,17 @@
{
int x;
- ast_rwlock_wrlock(&features_lock);
+ ast_wrlock_call_features();
for (x = 0; x < FEATURES_COUNT; x++)
strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
}
static int remap_feature(const char *name, const char *value)
{
int x, res = -1;
- ast_rwlock_wrlock(&features_lock);
+ ast_wrlock_call_features();
for (x = 0; x < FEATURES_COUNT; x++) {
if (strcasecmp(builtin_features[x].sname, name))
continue;
@@ -3405,7 +3407,7 @@
res = 0;
break;
}
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
return res;
}
@@ -3436,7 +3438,7 @@
return -1; /* can not run feature operation */
}
- ast_rwlock_rdlock(&features_lock);
+ ast_rdlock_call_features();
for (x = 0; x < FEATURES_COUNT; x++) {
char feature_exten[FEATURE_MAX_LEN] = "";
@@ -3478,7 +3480,7 @@
"Result: fail");
}
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
if (!dynamic_features_buf || !ast_str_strlen(dynamic_features_buf) || feature_detected) {
return res;
@@ -3488,9 +3490,7 @@
while ((tok = strsep(&tmp, "#"))) {
AST_RWLIST_RDLOCK(&feature_groups);
-
fg = find_group(tok);
-
if (fg) {
AST_LIST_TRAVERSE(&fg->features, fge, entry) {
if (!strcmp(fge->exten, code)) {
@@ -3513,13 +3513,12 @@
break;
}
}
-
AST_RWLIST_UNLOCK(&feature_groups);
- AST_RWLIST_RDLOCK(&feature_list);
+ ast_rdlock_call_features();
if (!(tmpfeature = find_dynamic_feature(tok))) {
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
continue;
}
@@ -3535,14 +3534,14 @@
memcpy(feature, tmpfeature, sizeof(*feature));
}
if (res != AST_FEATURE_RETURN_KEEPTRYING) {
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
break;
}
res = AST_FEATURE_RETURN_PASSDIGITS;
} else if (!strncmp(tmpfeature->exten, code, strlen(code)))
res = AST_FEATURE_RETURN_STOREDIGITS;
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
}
return res;
@@ -3629,7 +3628,7 @@
ast_clear_flag(config, AST_FLAGS_ALL);
- ast_rwlock_rdlock(&features_lock);
+ ast_rdlock_call_features();
for (x = 0; x < FEATURES_COUNT; x++) {
if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
continue;
@@ -3640,7 +3639,7 @@
if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
}
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
if (!(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
@@ -3655,7 +3654,8 @@
struct feature_group *fg;
AST_RWLIST_RDLOCK(&feature_groups);
- AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
+ fg = find_group(tok);
+ if (fg) {
struct feature_group_exten *fge;
AST_LIST_TRAVERSE(&fg->features, fge, entry) {
@@ -3669,7 +3669,7 @@
}
AST_RWLIST_UNLOCK(&feature_groups);
- AST_RWLIST_RDLOCK(&feature_list);
+ ast_rdlock_call_features();
if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
@@ -3678,7 +3678,7 @@
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
}
}
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
}
}
}
@@ -3794,7 +3794,7 @@
}
/* support dialing of the featuremap disconnect code while performing an attended tranfer */
- ast_rwlock_rdlock(&features_lock);
+ ast_rdlock_call_features();
for (x = 0; x < FEATURES_COUNT; x++) {
if (strcasecmp(builtin_features[x].sname, "disconnect"))
continue;
@@ -3805,7 +3805,7 @@
memset(dialed_code, 0, len);
break;
}
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
x = 0;
started = ast_tvnow();
to = timeout;
@@ -4197,7 +4197,6 @@
#else
return 0;
#endif
-/* BUGBUG dynamic features not handled yet. App run returns non-zero breaks bridge and ast_bridge_call returns 0. App returns zero continues bridge. */
}
static void bridge_config_set_limits_warning_values(struct ast_bridge_config *config, struct ast_bridge_features_limits *limits)
@@ -5312,14 +5311,14 @@
return;
}
- AST_RWLIST_RDLOCK(&feature_list);
+ ast_rdlock_call_features();
if (find_dynamic_feature(var->name)) {
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n",
var->name);
return;
}
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_unlock_call_features();
if (!(feature = ast_calloc(1, sizeof(*feature)))) {
return;
@@ -5521,14 +5520,13 @@
for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
struct ast_call_feature *feature;
- AST_RWLIST_RDLOCK(&feature_list);
- if (!(feature = find_dynamic_feature(var->name)) &&
- !(feature = ast_find_call_feature(var->name))) {
- AST_RWLIST_UNLOCK(&feature_list);
+ ast_rdlock_call_features();
+ feature = ast_find_call_feature(var->name);
+ ast_unlock_call_features();
+ if (!feature) {
ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
continue;
}
- AST_RWLIST_UNLOCK(&feature_list);
register_group_feature(fg, var->value, feature);
}
@@ -6326,41 +6324,41 @@
ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
- ast_rwlock_rdlock(&features_lock);
+ ast_rdlock_call_features();
for (i = 0; i < FEATURES_COUNT; i++)
ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
- ast_rwlock_unlock(&features_lock);
+ ast_unlock_call_features();
ast_cli(a->fd, "\n");
ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
- if (AST_RWLIST_EMPTY(&feature_list)) {
+ ast_rdlock_call_features();
+ if (AST_LIST_EMPTY(&feature_list)) {
ast_cli(a->fd, "(none)\n");
} else {
- AST_RWLIST_RDLOCK(&feature_list);
- AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
+ AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
}
- AST_RWLIST_UNLOCK(&feature_list);
- }
+ }
+ ast_unlock_call_features();
ast_cli(a->fd, "\nFeature Groups:\n");
ast_cli(a->fd, "---------------\n");
+ AST_RWLIST_RDLOCK(&feature_groups);
if (AST_RWLIST_EMPTY(&feature_groups)) {
ast_cli(a->fd, "(none)\n");
} else {
struct feature_group *fg;
struct feature_group_exten *fge;
- AST_RWLIST_RDLOCK(&feature_groups);
AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
ast_cli(a->fd, "===> Group: %s\n", fg->gname);
AST_LIST_TRAVERSE(&fg->features, fge, entry) {
ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
}
}
- AST_RWLIST_UNLOCK(&feature_groups);
- }
+ }
+ AST_RWLIST_UNLOCK(&feature_groups);
ast_cli(a->fd, "\n");
@@ -7928,8 +7926,12 @@
{
struct feature_datastore *feature_ds;
struct feature_exten *fe;
-
- if (!ast_find_call_feature(data)) {
+ struct ast_call_feature *feat;
+
+ ast_rdlock_call_features();
+ feat = ast_find_call_feature(data);
+ ast_unlock_call_features();
+ if (!feat) {
ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
return -1;
}
Modified: team/jrose/bridge_projects/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/manager.c?view=diff&rev=385308&r1=385307&r2=385308
==============================================================================
--- team/jrose/bridge_projects/main/manager.c (original)
+++ team/jrose/bridge_projects/main/manager.c Thu Apr 11 09:55:51 2013
@@ -3892,7 +3892,10 @@
return 0;
}
- if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
+ ast_rdlock_call_features();
+ atxfer_feature = ast_find_call_feature("atxfer");
+ ast_unlock_call_features();
+ if (!atxfer_feature) {
astman_send_error(s, m, "No attended transfer feature found");
return 0;
}
More information about the asterisk-commits
mailing list