This reverts the changes I made for 11583; will

reviewboard this before committing again...
reopened 11583 until all Russell's issues are
resolved.



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@172929 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Steve Murphy
2009-02-02 19:02:24 +00:00
parent fdcc0a9a60
commit 53d9b77898
4 changed files with 55 additions and 171 deletions

View File

@@ -128,8 +128,6 @@ Miscellaneous
* The contrib/scripts/ directory now has a script called sip_nat_settings that will * The contrib/scripts/ directory now has a script called sip_nat_settings that will
give you the correct output for an asterisk box behind nat. It will give you the give you the correct output for an asterisk box behind nat. It will give you the
externhost and localnet settings. externhost and localnet settings.
* The 'one-touch' disconnect feature is now available during Dial,
instead of just when a call is connected.
Asterisk Manager Interface Asterisk Manager Interface
-------------------------- --------------------------

View File

@@ -560,7 +560,6 @@ struct chanlist {
uint64_t flags; uint64_t flags;
}; };
static int detect_disconnect(struct ast_channel *chan, char code);
static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere) static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
{ {
@@ -1055,8 +1054,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
} }
if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
detect_disconnect(in, f->subclass)) { (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
ast_verb(3, "User requested call disconnect.\n"); ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
*to = 0; *to = 0;
strcpy(pa->status, "CANCEL"); strcpy(pa->status, "CANCEL");
ast_cdr_noanswer(in->cdr); ast_cdr_noanswer(in->cdr);
@@ -1100,58 +1099,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
return peer; return peer;
} }
static char featurecode[FEATURE_MAX_LEN + 1] = "";
static int detect_disconnect(struct ast_channel *chan, char code)
{
struct feature_interpret_result result;
int x;
struct ast_flags features;
int res = FEATURE_RETURN_PASSDIGITS;
struct ast_call_feature *feature;
char *cptr;
const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
int len;
len = strlen(featurecode);
if (len >= FEATURE_MAX_LEN) {
featurecode[0] = '\0';
}
cptr = &featurecode[strlen(featurecode)];
cptr[0] = code;
cptr[1] = '\0';
memset(&features, 0, sizeof(struct ast_flags));
ast_set_flag(&features, AST_FEATURE_DISCONNECT);
ast_features_lock();
res = ast_feature_detect(chan, &features, featurecode, &result, dynamic_features);
if (res != FEATURE_RETURN_STOREDIGITS)
featurecode[0] = '\0';
if (result.builtin_feature && result.builtin_feature->feature_mask & AST_FEATURE_DISCONNECT) {
ast_features_unlock();
return 1;
}
for (x = 0; x < result.num_dyn_features; ++x) {
feature = result.dynamic_features[x];
if (feature->feature_mask & AST_FEATURE_DISCONNECT) {
ast_features_unlock();
return 1;
}
}
ast_features_unlock();
return 0;
}
static void replace_macro_delimiter(char *s) static void replace_macro_delimiter(char *s)
{ {
for (; *s; s++) for (; *s; s++)

View File

@@ -36,15 +36,6 @@
#define PARK_APP_NAME "Park" #define PARK_APP_NAME "Park"
#define FEATURE_RETURN_HANGUP -1
#define FEATURE_RETURN_SUCCESSBREAK 0
#define FEATURE_RETURN_PASSDIGITS 21
#define FEATURE_RETURN_STOREDIGITS 22
#define FEATURE_RETURN_SUCCESS 23
#define FEATURE_RETURN_KEEPTRYING 24
typedef int (*feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
/*! \brief main call feature structure */ /*! \brief main call feature structure */
enum { enum {
@@ -62,7 +53,7 @@ struct ast_call_feature {
char sname[FEATURE_SNAME_LEN]; char sname[FEATURE_SNAME_LEN];
char exten[FEATURE_MAX_LEN]; char exten[FEATURE_MAX_LEN];
char default_exten[FEATURE_MAX_LEN]; char default_exten[FEATURE_MAX_LEN];
feature_operation operation; int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
unsigned int flags; unsigned int flags;
char app[FEATURE_APP_LEN]; char app[FEATURE_APP_LEN];
char app_args[FEATURE_APP_ARGS_LEN]; char app_args[FEATURE_APP_ARGS_LEN];
@@ -70,20 +61,12 @@ struct ast_call_feature {
AST_LIST_ENTRY(ast_call_feature) feature_entry; AST_LIST_ENTRY(ast_call_feature) feature_entry;
}; };
#define AST_FEATURE_RETURN_HANGUP FEATURE_RETURN_HANGUP #define AST_FEATURE_RETURN_HANGUP -1
#define AST_FEATURE_RETURN_SUCCESSBREAK FEATURE_RETURN_SUCCESSBREAK #define AST_FEATURE_RETURN_SUCCESSBREAK 0
#define AST_FEATURE_RETURN_PASSDIGITS FEATURE_RETURN_PASSDIGITS #define AST_FEATURE_RETURN_PASSDIGITS 21
#define AST_FEATURE_RETURN_STOREDIGITS FEATURE_RETURN_STOREDIGITS #define AST_FEATURE_RETURN_STOREDIGITS 22
#define AST_FEATURE_RETURN_SUCCESS FEATURE_RETURN_SUCCESS #define AST_FEATURE_RETURN_SUCCESS 23
#define AST_FEATURE_RETURN_KEEPTRYING FEATURE_RETURN_KEEPTRYING #define AST_FEATURE_RETURN_KEEPTRYING 24
struct feature_interpret_result {
struct ast_call_feature *builtin_feature;
struct ast_call_feature *dynamic_features[20];
struct ast_call_feature *group_features[20];
int num_dyn_features;
int num_grp_features;
};
/*! /*!
* \brief Park a call and read back parked location * \brief Park a call and read back parked location
@@ -139,12 +122,6 @@ void ast_register_feature(struct ast_call_feature *feature);
\param feature the ast_call_feature object which was registered before*/ \param feature the ast_call_feature object which was registered before*/
void ast_unregister_feature(struct ast_call_feature *feature); void ast_unregister_feature(struct ast_call_feature *feature);
int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *features, char *code, struct feature_interpret_result *result, const char *dynamic_features);
void ast_features_lock(void);
void ast_features_unlock(void);
/*! \brief look for a call feature entry by its sname /*! \brief look for a call feature entry by its sname
\param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */ \param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */
struct ast_call_feature *ast_find_call_feature(const char *name); struct ast_call_feature *ast_find_call_feature(const char *name);

View File

@@ -856,8 +856,8 @@ static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel
return masq_park_call(rchan, peer, timeout, extout, 1, NULL); return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
} }
#define FEATURE_SENSE_CHAN (1 << 0) #define FEATURE_SENSE_CHAN (1 << 0)
#define FEATURE_SENSE_PEER (1 << 1) #define FEATURE_SENSE_PEER (1 << 1)
/*! /*!
* \brief set caller and callee according to the direction * \brief set caller and callee according to the direction
@@ -1935,40 +1935,44 @@ static int remap_feature(const char *name, const char *value)
return res; return res;
} }
void ast_features_lock(void) /*!
{ * \brief Check the dynamic features
ast_rwlock_rdlock(&features_lock); * \param chan,peer,config,code,sense
AST_RWLIST_WRLOCK(&feature_list); *
AST_RWLIST_RDLOCK(&feature_groups); * Lock features list, browse for code, unlock list
} * \retval res on success.
* \retval -1 on failure.
void ast_features_unlock(void) */
{ static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
AST_RWLIST_UNLOCK(&feature_groups);
AST_RWLIST_UNLOCK(&feature_list);
ast_rwlock_unlock(&features_lock);
}
int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *features, char *code, struct feature_interpret_result *result, const char *dynamic_features)
{ {
int x; int x;
int res = FEATURE_RETURN_PASSDIGITS; struct ast_flags features;
struct ast_call_feature *feature; struct ast_call_feature *feature;
struct feature_group *fg = NULL; struct feature_group *fg = NULL;
struct feature_group_exten *fge; struct feature_group_exten *fge;
const char *dynamic_features;
char *tmp, *tok; char *tmp, *tok;
int res = AST_FEATURE_RETURN_PASSDIGITS;
result->builtin_feature = NULL; int feature_detected = 0;
result->num_dyn_features = 0;
result->num_grp_features = 0; if (sense == FEATURE_SENSE_CHAN) {
ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
}
else {
ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
}
ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
ast_rwlock_rdlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) { for (x = 0; x < FEATURES_COUNT; x++) {
if ((ast_test_flag(features, builtin_features[x].feature_mask)) && if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
!ast_strlen_zero(builtin_features[x].exten)) { !ast_strlen_zero(builtin_features[x].exten)) {
/* Feature is up for consideration */ /* Feature is up for consideration */
if (!strcmp(builtin_features[x].exten, code)) { if (!strcmp(builtin_features[x].exten, code)) {
result->builtin_feature = &builtin_features[x]; res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
feature_detected = 1;
break; break;
} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) { } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
if (res == AST_FEATURE_RETURN_PASSDIGITS) if (res == AST_FEATURE_RETURN_PASSDIGITS)
@@ -1976,13 +1980,15 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
} }
} }
} }
ast_rwlock_unlock(&features_lock);
if (ast_strlen_zero(dynamic_features)) if (ast_strlen_zero(dynamic_features) || feature_detected)
return res; return res;
tmp = ast_strdupa(dynamic_features); tmp = ast_strdupa(dynamic_features);
while ((tok = strsep(&tmp, "#"))) { while ((tok = strsep(&tmp, "#"))) {
AST_RWLIST_RDLOCK(&feature_groups);
fg = find_group(tok); fg = find_group(tok);
@@ -1990,9 +1996,10 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
AST_LIST_TRAVERSE(&fg->features, fge, entry) { AST_LIST_TRAVERSE(&fg->features, fge, entry) {
if (strcasecmp(fge->exten, code)) if (strcasecmp(fge->exten, code))
continue; continue;
result->group_features[result->num_grp_features++] = fge->feature; res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
if (result->num_grp_features >= (sizeof(result->group_features) / sizeof(result->group_features[0]))) { if (res != AST_FEATURE_RETURN_KEEPTRYING) {
AST_RWLIST_UNLOCK(&feature_groups);
break; break;
} }
res = AST_FEATURE_RETURN_PASSDIGITS; res = AST_FEATURE_RETURN_PASSDIGITS;
@@ -2001,74 +2008,29 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
break; break;
} }
AST_RWLIST_UNLOCK(&feature_groups);
AST_RWLIST_RDLOCK(&feature_list);
if (!(feature = find_dynamic_feature(tok))) { if (!(feature = find_dynamic_feature(tok))) {
AST_RWLIST_UNLOCK(&feature_list);
continue; continue;
} }
/* Feature is up for consideration */ /* Feature is up for consideration */
if (!strcmp(feature->exten, code)) { if (!strcmp(feature->exten, code)) {
ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok); ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
result->dynamic_features[result->num_dyn_features++] = feature; res = feature->operation(chan, peer, config, code, sense, feature);
if (result->num_dyn_features >= (sizeof(result->dynamic_features) / sizeof(result->dynamic_features[0]))) { if (res != AST_FEATURE_RETURN_KEEPTRYING) {
AST_RWLIST_UNLOCK(&feature_list);
break; break;
} }
res = AST_FEATURE_RETURN_PASSDIGITS; res = AST_FEATURE_RETURN_PASSDIGITS;
} else if (!strncmp(feature->exten, code, strlen(code))) } else if (!strncmp(feature->exten, code, strlen(code)))
res = AST_FEATURE_RETURN_STOREDIGITS; res = AST_FEATURE_RETURN_STOREDIGITS;
}
return res;
}
/*! AST_RWLIST_UNLOCK(&feature_list);
* \brief Check the dynamic features
* \param chan,peer,config,code,sense
*
* Lock features list, browse for code, unlock list
* \retval res on success.
* \retval -1 on failure.
*/
static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
{
struct feature_interpret_result result;
int x;
struct ast_flags features;
int res = AST_FEATURE_RETURN_PASSDIGITS;
struct ast_call_feature *feature;
const char *dynamic_features;
if (sense == FEATURE_SENSE_CHAN) {
ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
} else {
ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
} }
ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
ast_features_lock();
res = ast_feature_detect(chan, &features, code, &result, dynamic_features);
if (result.builtin_feature) {
res = result.builtin_feature->operation(chan, peer, config, code, sense, NULL);
}
for (x = 0; x < result.num_grp_features; ++x) {
feature = result.group_features[x];
res = feature->operation(chan, peer, config, code, sense, feature);
if (res != FEATURE_RETURN_KEEPTRYING) {
break;
}
res = FEATURE_RETURN_PASSDIGITS;
}
for (x = 0; x < result.num_dyn_features; ++x) {
feature = result.dynamic_features[x];
res = feature->operation(chan, peer, config, code, sense, feature);
if (res != FEATURE_RETURN_KEEPTRYING) {
break;
}
res = FEATURE_RETURN_PASSDIGITS;
}
ast_features_unlock();
return res; return res;
} }