mirror of
https://git.freebsd.org/ports.git
synced 2025-06-22 13:10:31 -04:00
o move all additional functionality into separate patches and make it opt in. It has been concern of asterisks devs that the FreeBSD pacakage adds functionalty not present in the original version, whch could be confusing.
292 lines
9.6 KiB
Diff
292 lines
9.6 KiB
Diff
--- apps/app_dial.c.orig Wed Feb 6 18:45:30 2008
|
|
+++ apps/app_dial.c Wed Feb 6 18:51:59 2008
|
|
@@ -297,6 +297,8 @@ AST_APP_OPTIONS(dial_exec_options, {
|
|
OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
|
|
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
|
|
|
|
+static int detect_disconnect(struct ast_channel *chan, char code);
|
|
+
|
|
/* We define a custom "local user" structure because we
|
|
use it not only for keeping track of what is in use but
|
|
also for keeping track of who we're dialing. */
|
|
@@ -402,6 +404,7 @@ static struct ast_channel *wait_for_answ
|
|
struct ast_channel *peer = NULL;
|
|
/* single is set if only one destination is enabled */
|
|
int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
|
|
+
|
|
|
|
if (single) {
|
|
/* Turn off hold music, etc */
|
|
@@ -716,9 +719,9 @@ static struct ast_channel *wait_for_answ
|
|
}
|
|
|
|
if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) &&
|
|
- (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
|
|
+ detect_disconnect(in, f->subclass)) { /* hmm it it not guaranteed to be '*' anymore. */
|
|
if (option_verbose > 2)
|
|
- ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
|
|
+ ast_verbose(VERBOSE_PREFIX_3 "User requested call disconnect.\n");
|
|
*to=0;
|
|
ast_cdr_noanswer(in->cdr);
|
|
strcpy(status, "CANCEL");
|
|
@@ -776,6 +779,56 @@ static struct ast_channel *wait_for_answ
|
|
|
|
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;
|
|
+ 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);
|
|
+
|
|
+ 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)
|
|
{
|
|
--- include/asterisk/features.h.orig Thu Aug 23 23:16:41 2007
|
|
+++ include/asterisk/features.h Tue Dec 11 17:13:52 2007
|
|
@@ -31,6 +31,20 @@
|
|
#define FEATURE_EXTEN_LEN 32
|
|
#define FEATURE_MOH_LEN 80 /* same as MAX_MUSICCLASS from channel.h */
|
|
|
|
+#define FEATURE_RETURN_HANGUP -1
|
|
+#define FEATURE_RETURN_SUCCESSBREAK 0
|
|
+#define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
|
|
+#define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
|
|
+#define FEATURE_RETURN_PASSDIGITS 21
|
|
+#define FEATURE_RETURN_STOREDIGITS 22
|
|
+#define FEATURE_RETURN_SUCCESS 23
|
|
+#define FEATURE_RETURN_KEEPTRYING 24
|
|
+
|
|
+#define FEATURE_SENSE_CHAN (1 << 0)
|
|
+#define FEATURE_SENSE_PEER (1 << 1)
|
|
+
|
|
+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 */
|
|
struct ast_call_feature {
|
|
int feature_mask;
|
|
@@ -38,7 +52,7 @@
|
|
char sname[FEATURE_SNAME_LEN];
|
|
char exten[FEATURE_MAX_LEN];
|
|
char default_exten[FEATURE_MAX_LEN];
|
|
- int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
|
|
+ feature_operation operation;
|
|
unsigned int flags;
|
|
char app[FEATURE_APP_LEN];
|
|
char app_args[FEATURE_APP_ARGS_LEN];
|
|
@@ -47,6 +61,12 @@
|
|
};
|
|
|
|
|
|
+struct feature_interpret_result {
|
|
+ struct ast_call_feature *builtin_feature;
|
|
+ struct ast_call_feature *dynamic_features[20];
|
|
+ int num_dyn_features;
|
|
+};
|
|
+
|
|
|
|
/*! \brief Park a call and read back parked location
|
|
* \param chan the channel to actually be parked
|
|
@@ -93,5 +113,11 @@
|
|
/*! \brief unregister feature from feature_set
|
|
\param feature the ast_call_feature object which was registered before*/
|
|
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);
|
|
+
|
|
+void ast_features_lock(void);
|
|
+void ast_features_unlock(void);
|
|
+
|
|
|
|
#endif /* _AST_FEATURES_H */
|
|
--- res/res_features.c.orig 2008-04-08 14:55:25.000000000 +0300
|
|
+++ res/res_features.c 2008-04-08 14:59:59.000000000 +0300
|
|
@@ -485,18 +485,6 @@
|
|
}
|
|
|
|
|
|
-#define FEATURE_RETURN_HANGUP -1
|
|
-#define FEATURE_RETURN_SUCCESSBREAK 0
|
|
-#define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
|
|
-#define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
|
|
-#define FEATURE_RETURN_PASSDIGITS 21
|
|
-#define FEATURE_RETURN_STOREDIGITS 22
|
|
-#define FEATURE_RETURN_SUCCESS 23
|
|
-#define FEATURE_RETURN_KEEPTRYING 24
|
|
-
|
|
-#define FEATURE_SENSE_CHAN (1 << 0)
|
|
-#define FEATURE_SENSE_PEER (1 << 1)
|
|
-
|
|
/*! \brief
|
|
* set caller and callee according to the direction
|
|
*/
|
|
@@ -1061,32 +1049,35 @@
|
|
return res;
|
|
}
|
|
|
|
-static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
|
|
+void ast_features_lock(void)
|
|
+{
|
|
+ ast_rwlock_rdlock(&features_lock);
|
|
+ AST_LIST_LOCK(&feature_list);
|
|
+}
|
|
+
|
|
+void ast_features_unlock(void)
|
|
+{
|
|
+ AST_LIST_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)
|
|
{
|
|
int x;
|
|
- struct ast_flags features;
|
|
int res = FEATURE_RETURN_PASSDIGITS;
|
|
struct ast_call_feature *feature;
|
|
- const char *dynamic_features;
|
|
+ const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
|
|
char *tmp, *tok;
|
|
|
|
- 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");
|
|
- }
|
|
- if (option_debug > 2)
|
|
- ast_log(LOG_DEBUG, "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);
|
|
+ result->builtin_feature = NULL;
|
|
+ result->num_dyn_features = 0;
|
|
|
|
- ast_rwlock_rdlock(&features_lock);
|
|
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)) {
|
|
/* Feature is up for consideration */
|
|
if (!strcmp(builtin_features[x].exten, code)) {
|
|
- res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
|
|
+ result->builtin_feature = &builtin_features[x];
|
|
break;
|
|
} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
|
|
if (res == FEATURE_RETURN_PASSDIGITS)
|
|
@@ -1094,7 +1085,6 @@
|
|
}
|
|
}
|
|
}
|
|
- ast_rwlock_unlock(&features_lock);
|
|
|
|
if (ast_strlen_zero(dynamic_features))
|
|
return res;
|
|
@@ -1102,9 +1092,7 @@
|
|
tmp = ast_strdupa(dynamic_features);
|
|
|
|
while ((tok = strsep(&tmp, "#"))) {
|
|
- AST_LIST_LOCK(&feature_list);
|
|
if (!(feature = find_dynamic_feature(tok))) {
|
|
- AST_LIST_UNLOCK(&feature_list);
|
|
continue;
|
|
}
|
|
|
|
@@ -1112,21 +1100,52 @@
|
|
if (!strcmp(feature->exten, code)) {
|
|
if (option_verbose > 2)
|
|
ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
|
|
- res = feature->operation(chan, peer, config, code, sense, feature);
|
|
- if (res != FEATURE_RETURN_KEEPTRYING) {
|
|
- AST_LIST_UNLOCK(&feature_list);
|
|
+ result->dynamic_features[result->num_dyn_features++] = feature;
|
|
+ if (result->num_dyn_features >= (sizeof(result->dynamic_features) / sizeof(result->dynamic_features[0]))) {
|
|
break;
|
|
}
|
|
res = FEATURE_RETURN_PASSDIGITS;
|
|
} else if (!strncmp(feature->exten, code, strlen(code)))
|
|
res = FEATURE_RETURN_STOREDIGITS;
|
|
|
|
- AST_LIST_UNLOCK(&feature_list);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
+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 = FEATURE_RETURN_PASSDIGITS;
|
|
+ struct ast_call_feature *feature;
|
|
+
|
|
+ if (sense == FEATURE_SENSE_CHAN)
|
|
+ ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
|
|
+ else
|
|
+ ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
|
|
+ if (option_debug > 2)
|
|
+ ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
|
|
+
|
|
+ ast_features_lock();
|
|
+ res = ast_feature_detect(chan, &features, code, &result);
|
|
+
|
|
+ if (result.builtin_feature)
|
|
+ res = result.builtin_feature->operation(chan, peer, config, code, sense, NULL);
|
|
+
|
|
+ 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;
|
|
+}
|
|
+
|
|
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
|
|
{
|
|
int x;
|