325
325
parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
326
326
if (!ast_strlen_zero(parkingexten)) {
327
327
if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
328
ast_mutex_unlock(&parking_lock);
328
330
ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
329
return 0; /* Continue execution if possible */
331
return -1; /* We failed to park this call, plain and simple so we need to error out */
331
333
ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
334
x = atoi(parkingexten);
333
336
/* Select parking space within range */
334
337
parking_range = parking_stop - parking_start+1;
814
817
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
815
818
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
816
819
res = ast_bridge_call(transferer, newchan, &bconfig);
817
if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
820
if (newchan->_softhangup || !transferer->_softhangup) {
818
821
ast_hangup(newchan);
819
822
if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
820
823
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
878
881
/* add atxfer and automon as undefined so you can only use em if you configure them */
879
882
#define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
881
struct ast_call_feature builtin_features[] =
884
AST_RWLOCK_DEFINE_STATIC(features_lock);
886
static struct ast_call_feature builtin_features[] =
883
888
{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
884
889
{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
932
937
/*! \brief find a feature by name */
933
static struct ast_call_feature *find_feature(char *name)
938
static struct ast_call_feature *find_dynamic_feature(const char *name)
935
940
struct ast_call_feature *tmp;
937
AST_LIST_LOCK(&feature_list);
938
942
AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
939
943
if (!strcasecmp(tmp->sname, name))
942
AST_LIST_UNLOCK(&feature_list);
1016
1019
static void unmap_features(void)
1023
ast_rwlock_wrlock(&features_lock);
1019
1024
for (x = 0; x < FEATURES_COUNT; x++)
1020
1025
strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1026
ast_rwlock_unlock(&features_lock);
1023
1029
static int remap_feature(const char *name, const char *value)
1033
ast_rwlock_wrlock(&features_lock);
1027
1034
for (x = 0; x < FEATURES_COUNT; x++) {
1028
if (!strcasecmp(name, builtin_features[x].sname)) {
1029
ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1030
if (option_verbose > 1)
1031
ast_verbose(VERBOSE_PREFIX_2 "Remapping feature %s (%s) to sequence '%s'\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
1033
} else if (!strcmp(value, builtin_features[x].exten))
1034
ast_log(LOG_WARNING, "Sequence '%s' already mapped to function %s (%s) while assigning to %s\n", value, builtin_features[x].fname, builtin_features[x].sname, name);
1035
if (strcasecmp(builtin_features[x].sname, name))
1038
ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1042
ast_rwlock_unlock(&features_lock);
1043
1051
int res = FEATURE_RETURN_PASSDIGITS;
1044
1052
struct ast_call_feature *feature;
1045
1053
const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1047
1056
if (sense == FEATURE_SENSE_CHAN)
1048
1057
ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1051
1060
if (option_debug > 2)
1052
1061
ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1054
for (x=0; x < FEATURES_COUNT; x++) {
1063
ast_rwlock_rdlock(&features_lock);
1064
for (x = 0; x < FEATURES_COUNT; x++) {
1055
1065
if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1056
1066
!ast_strlen_zero(builtin_features[x].exten)) {
1057
1067
/* Feature is up for consideration */
1069
if (!ast_strlen_zero(dynamic_features)) {
1070
char *tmp = ast_strdupa(dynamic_features);
1073
while ((tok = strsep(&tmp, "#")) != NULL) {
1074
feature = find_feature(tok);
1077
ast_rwlock_unlock(&features_lock);
1079
if (ast_strlen_zero(dynamic_features))
1082
tmp = ast_strdupa(dynamic_features);
1084
while ((tok = strsep(&tmp, "#"))) {
1085
AST_LIST_LOCK(&feature_list);
1086
if (!(feature = find_dynamic_feature(tok))) {
1087
AST_LIST_UNLOCK(&feature_list);
1077
/* Feature is up for consideration */
1078
if (!strcmp(feature->exten, code)) {
1079
if (option_verbose > 2)
1080
ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1081
res = feature->operation(chan, peer, config, code, sense);
1083
} else if (!strncmp(feature->exten, code, strlen(code))) {
1084
res = FEATURE_RETURN_STOREDIGITS;
1091
/* Feature is up for consideration */
1092
if (!strcmp(feature->exten, code)) {
1093
if (option_verbose > 2)
1094
ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1095
res = feature->operation(chan, peer, config, code, sense);
1096
AST_LIST_UNLOCK(&feature_list);
1098
} else if (!strncmp(feature->exten, code, strlen(code)))
1099
res = FEATURE_RETURN_STOREDIGITS;
1101
AST_LIST_UNLOCK(&feature_list);
1097
ast_clear_flag(config, AST_FLAGS_ALL);
1111
ast_clear_flag(config, AST_FLAGS_ALL);
1113
ast_rwlock_rdlock(&features_lock);
1098
1114
for (x = 0; x < FEATURES_COUNT; x++) {
1099
if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1100
if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1101
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1103
if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1104
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1115
if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1118
if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1119
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1121
if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1122
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1124
ast_rwlock_unlock(&features_lock);
1108
1126
if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1109
1127
const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1116
1134
/* while we have a feature */
1117
1135
while ((tok = strsep(&tmp, "#"))) {
1118
if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1136
AST_LIST_LOCK(&feature_list);
1137
if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1119
1138
if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1120
1139
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1121
1140
if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1122
1141
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1143
AST_LIST_UNLOCK(&feature_list);
1157
1177
ast_indicate(caller, AST_CONTROL_RINGING);
1158
1178
/* support dialing of the featuremap disconnect code while performing an attended tranfer */
1159
for (x=0; x < FEATURES_COUNT; x++) {
1179
ast_rwlock_rdlock(&features_lock);
1180
for (x = 0; x < FEATURES_COUNT; x++) {
1160
1181
if (strcasecmp(builtin_features[x].sname, "disconnect"))
1927
1948
ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
1929
fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1931
for (i = 0; i < fcount; i++)
1950
ast_rwlock_rdlock(&features_lock);
1951
for (i = 0; i < FEATURES_COUNT; i++)
1933
1952
ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1953
ast_rwlock_unlock(&features_lock);
1935
1955
ast_cli(fd, "\n");
1936
1956
ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1937
1957
ast_cli(fd, format, "---------------", "-------", "-------");
1938
if (AST_LIST_EMPTY(&feature_list)) {
1958
if (AST_LIST_EMPTY(&feature_list))
1939
1959
ast_cli(fd, "(none)\n");
1942
1961
AST_LIST_LOCK(&feature_list);
1943
AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1962
AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
1944
1963
ast_cli(fd, format, feature->sname, "no def", feature->exten);
1946
1964
AST_LIST_UNLOCK(&feature_list);
1948
1966
ast_cli(fd, "\nCall parking\n");
2290
if ((feature = find_feature(var->name))) {
2308
AST_LIST_LOCK(&feature_list);
2309
if ((feature = find_dynamic_feature(var->name))) {
2310
AST_LIST_UNLOCK(&feature_list);
2291
2311
ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2314
AST_LIST_UNLOCK(&feature_list);
2295
2316
if (!(feature = ast_calloc(1, sizeof(*feature))))