~davewalker/ubuntu/maverick/asterisk/lp_705014

« back to all changes in this revision

Viewing changes to res/res_features.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Porcheron
  • Date: 2007-06-19 18:08:27 UTC
  • mto: (1.2.1 upstream) (8.2.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20070619180827-4d9gqoqys7kel3yk
Tags: upstream-1.4.5~dfsg
ImportĀ upstreamĀ versionĀ 1.4.5~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
#include "asterisk.h"
27
27
 
28
 
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 61136 $")
 
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 69579 $")
29
29
 
30
30
#include <pthread.h>
31
31
#include <stdlib.h>
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);
 
329
                        free(pu);
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 */
330
332
                }
331
333
                ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
 
334
                x = atoi(parkingexten);
332
335
        } else {
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]))
880
883
 
881
 
struct ast_call_feature builtin_features[] = 
 
884
AST_RWLOCK_DEFINE_STATIC(features_lock);
 
885
 
 
886
static struct ast_call_feature builtin_features[] = 
882
887
 {
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, "" },
930
935
}
931
936
 
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)
934
939
{
935
940
        struct ast_call_feature *tmp;
936
941
 
937
 
        AST_LIST_LOCK(&feature_list);
938
942
        AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
939
943
                if (!strcasecmp(tmp->sname, name))
940
944
                        break;
941
945
        }
942
 
        AST_LIST_UNLOCK(&feature_list);
943
946
 
944
947
        return tmp;
945
948
}
1016
1019
static void unmap_features(void)
1017
1020
{
1018
1021
        int x;
 
1022
 
 
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);
1021
1027
}
1022
1028
 
1023
1029
static int remap_feature(const char *name, const char *value)
1024
1030
{
1025
 
        int x;
1026
 
        int res = -1;
 
1031
        int x, res = -1;
 
1032
 
 
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);
1032
 
                        res = 0;
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))
 
1036
                        continue;
 
1037
 
 
1038
                ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
 
1039
                res = 0;
 
1040
                break;
1035
1041
        }
 
1042
        ast_rwlock_unlock(&features_lock);
 
1043
 
1036
1044
        return res;
1037
1045
}
1038
1046
 
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");
 
1054
        char *tmp, *tok;
1046
1055
 
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);
1053
1062
 
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 */
1064
1074
                        }
1065
1075
                }
1066
1076
        }
1067
 
 
1068
 
 
1069
 
        if (!ast_strlen_zero(dynamic_features)) {
1070
 
                char *tmp = ast_strdupa(dynamic_features);
1071
 
                char *tok;
1072
 
 
1073
 
                while ((tok = strsep(&tmp, "#")) != NULL) {
1074
 
                        feature = find_feature(tok);
 
1077
        ast_rwlock_unlock(&features_lock);
 
1078
 
 
1079
        if (ast_strlen_zero(dynamic_features))
 
1080
                return res;
 
1081
 
 
1082
        tmp = ast_strdupa(dynamic_features);
 
1083
 
 
1084
        while ((tok = strsep(&tmp, "#"))) {
 
1085
                AST_LIST_LOCK(&feature_list);   
 
1086
                if (!(feature = find_dynamic_feature(tok))) {
 
1087
                        AST_LIST_UNLOCK(&feature_list);
 
1088
                        continue;
 
1089
                }
1075
1090
                        
1076
 
                        if (feature) {
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);
1082
 
                                        break;
1083
 
                                } else if (!strncmp(feature->exten, code, strlen(code))) {
1084
 
                                        res = FEATURE_RETURN_STOREDIGITS;
1085
 
                                }
1086
 
                        }
1087
 
                }
 
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);
 
1097
                        break;
 
1098
                } else if (!strncmp(feature->exten, code, strlen(code)))
 
1099
                        res = FEATURE_RETURN_STOREDIGITS;
 
1100
 
 
1101
                AST_LIST_UNLOCK(&feature_list);
1088
1102
        }
1089
1103
        
1090
1104
        return res;
1094
1108
{
1095
1109
        int x;
1096
1110
        
1097
 
        ast_clear_flag(config, AST_FLAGS_ALL);  
 
1111
        ast_clear_flag(config, AST_FLAGS_ALL);
 
1112
 
 
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);
1102
 
 
1103
 
                        if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1104
 
                                ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1105
 
                }
 
1115
                if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
 
1116
                        continue;
 
1117
 
 
1118
                if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
 
1119
                        ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
 
1120
 
 
1121
                if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
 
1122
                        ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1106
1123
        }
 
1124
        ast_rwlock_unlock(&features_lock);
1107
1125
        
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");
1115
1133
 
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);
1123
1142
                                }
 
1143
                                AST_LIST_UNLOCK(&feature_list);
1124
1144
                        }
1125
1145
                }
1126
1146
        }
1156
1176
 
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"))
1161
1182
                                        continue;
1162
1183
 
1166
1187
                                memset(dialed_code, 0, len);
1167
1188
                                break;
1168
1189
                        }
 
1190
                        ast_rwlock_unlock(&features_lock);
1169
1191
                        x = 0;
1170
1192
                        started = ast_tvnow();
1171
1193
                        to = timeout;
1917
1939
static int handle_showfeatures(int fd, int argc, char *argv[])
1918
1940
{
1919
1941
        int i;
1920
 
        int fcount;
1921
1942
        struct ast_call_feature *feature;
1922
1943
        char format[] = "%-25s %-7s %-7s\n";
1923
1944
 
1926
1947
 
1927
1948
        ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1928
1949
 
1929
 
        fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1930
 
 
1931
 
        for (i = 0; i < fcount; i++)
1932
 
        {
 
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);
1934
 
        }
 
1953
        ast_rwlock_unlock(&features_lock);
 
1954
 
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");
1940
 
        }
1941
1960
        else {
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);  
1945
 
                }
1946
1964
                AST_LIST_UNLOCK(&feature_list);
1947
1965
        }
1948
1966
        ast_cli(fd, "\nCall parking\n");
2287
2305
                        continue;
2288
2306
                }
2289
2307
 
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);
2292
2312
                        continue;
2293
2313
                }
 
2314
                AST_LIST_UNLOCK(&feature_list);
2294
2315
                                
2295
2316
                if (!(feature = ast_calloc(1, sizeof(*feature))))
2296
2317
                        continue;