mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-29 23:39:35 +00:00 
			
		
		
		
	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:
		
							
								
								
									
										2
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -128,8 +128,6 @@ Miscellaneous | ||||
|  * 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 | ||||
|    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 | ||||
| -------------------------- | ||||
|   | ||||
| @@ -560,7 +560,6 @@ struct chanlist { | ||||
| 	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) | ||||
| { | ||||
| @@ -1055,8 +1054,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, | ||||
| 				} | ||||
|  | ||||
| 				if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && | ||||
| 						detect_disconnect(in, f->subclass)) { | ||||
| 					ast_verb(3, "User requested call disconnect.\n"); | ||||
| 						(f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */ | ||||
| 					ast_verb(3, "User hit %c to disconnect call.\n", f->subclass); | ||||
| 					*to = 0; | ||||
| 					strcpy(pa->status, "CANCEL"); | ||||
| 					ast_cdr_noanswer(in->cdr); | ||||
| @@ -1100,58 +1099,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, | ||||
| 	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) | ||||
| { | ||||
| 	for (; *s; s++) | ||||
|   | ||||
| @@ -36,15 +36,6 @@ | ||||
|  | ||||
| #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 */ | ||||
|  | ||||
| enum { | ||||
| @@ -62,7 +53,7 @@ struct ast_call_feature { | ||||
| 	char sname[FEATURE_SNAME_LEN]; | ||||
| 	char 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; | ||||
| 	char app[FEATURE_APP_LEN];		 | ||||
| 	char app_args[FEATURE_APP_ARGS_LEN]; | ||||
| @@ -70,20 +61,12 @@ struct ast_call_feature { | ||||
| 	AST_LIST_ENTRY(ast_call_feature) feature_entry; | ||||
| }; | ||||
|  | ||||
| #define AST_FEATURE_RETURN_HANGUP                   FEATURE_RETURN_HANGUP | ||||
| #define AST_FEATURE_RETURN_SUCCESSBREAK             FEATURE_RETURN_SUCCESSBREAK | ||||
| #define AST_FEATURE_RETURN_PASSDIGITS               FEATURE_RETURN_PASSDIGITS | ||||
| #define AST_FEATURE_RETURN_STOREDIGITS              FEATURE_RETURN_STOREDIGITS | ||||
| #define AST_FEATURE_RETURN_SUCCESS                  FEATURE_RETURN_SUCCESS | ||||
| #define AST_FEATURE_RETURN_KEEPTRYING               FEATURE_RETURN_KEEPTRYING | ||||
|  | ||||
| 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; | ||||
| }; | ||||
| #define AST_FEATURE_RETURN_HANGUP                   -1 | ||||
| #define AST_FEATURE_RETURN_SUCCESSBREAK             0 | ||||
| #define AST_FEATURE_RETURN_PASSDIGITS               21 | ||||
| #define AST_FEATURE_RETURN_STOREDIGITS              22 | ||||
| #define AST_FEATURE_RETURN_SUCCESS                  23 | ||||
| #define AST_FEATURE_RETURN_KEEPTRYING               24 | ||||
|  | ||||
| /*! | ||||
|  * \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*/ | ||||
| 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 | ||||
| 	\param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */ | ||||
| struct ast_call_feature *ast_find_call_feature(const char *name); | ||||
|   | ||||
							
								
								
									
										168
									
								
								main/features.c
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								main/features.c
									
									
									
									
									
								
							| @@ -1935,90 +1935,6 @@ static int remap_feature(const char *name, const char *value) | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| void ast_features_lock(void) | ||||
| { | ||||
| 	ast_rwlock_rdlock(&features_lock); | ||||
| 	AST_RWLIST_WRLOCK(&feature_list); | ||||
| 	AST_RWLIST_RDLOCK(&feature_groups); | ||||
| } | ||||
|  | ||||
| void ast_features_unlock(void) | ||||
| { | ||||
| 	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 res = FEATURE_RETURN_PASSDIGITS; | ||||
| 	struct ast_call_feature *feature; | ||||
| 	struct feature_group *fg = NULL; | ||||
| 	struct feature_group_exten *fge; | ||||
| 	char *tmp, *tok; | ||||
| 	 | ||||
| 	result->builtin_feature = NULL; | ||||
| 	result->num_dyn_features = 0; | ||||
| 	result->num_grp_features = 0; | ||||
| 	 | ||||
| 	 | ||||
| 	for (x = 0; x < FEATURES_COUNT; x++) { | ||||
| 		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)) { | ||||
| 				result->builtin_feature = &builtin_features[x]; | ||||
| 				break; | ||||
| 			} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) { | ||||
| 				if (res == AST_FEATURE_RETURN_PASSDIGITS) | ||||
| 					res = AST_FEATURE_RETURN_STOREDIGITS; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (ast_strlen_zero(dynamic_features)) | ||||
| 		return res; | ||||
|  | ||||
| 	tmp = ast_strdupa(dynamic_features); | ||||
|  | ||||
| 	while ((tok = strsep(&tmp, "#"))) { | ||||
|  | ||||
| 		fg = find_group(tok); | ||||
|  | ||||
| 		if (fg) { | ||||
| 			AST_LIST_TRAVERSE(&fg->features, fge, entry) { | ||||
| 				if (strcasecmp(fge->exten, code)) | ||||
| 					continue; | ||||
| 				 | ||||
| 				result->group_features[result->num_grp_features++] = fge->feature; | ||||
| 				if (result->num_grp_features >= (sizeof(result->group_features) / sizeof(result->group_features[0]))) { | ||||
| 					break; | ||||
| 				} | ||||
| 				res = AST_FEATURE_RETURN_PASSDIGITS; | ||||
| 			} | ||||
| 			if (fge) | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| 		if (!(feature = find_dynamic_feature(tok))) { | ||||
| 			continue; | ||||
| 		} | ||||
| 			 | ||||
| 		/* Feature is up for consideration */ | ||||
| 		if (!strcmp(feature->exten, code)) { | ||||
| 			ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok); | ||||
| 			result->dynamic_features[result->num_dyn_features++] = feature; | ||||
| 			if (result->num_dyn_features >= (sizeof(result->dynamic_features) / sizeof(result->dynamic_features[0]))) { | ||||
| 				break; | ||||
| 			} | ||||
| 			res = AST_FEATURE_RETURN_PASSDIGITS; | ||||
| 		} else if (!strncmp(feature->exten, code, strlen(code))) | ||||
| 			res = AST_FEATURE_RETURN_STOREDIGITS; | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \brief Check the dynamic features | ||||
|  * \param chan,peer,config,code,sense | ||||
| @@ -2029,46 +1945,92 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature | ||||
| */ | ||||
| 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; | ||||
| 	struct feature_group *fg = NULL; | ||||
| 	struct feature_group_exten *fge; | ||||
| 	const char *dynamic_features; | ||||
| 	char *tmp, *tok; | ||||
| 	int res = AST_FEATURE_RETURN_PASSDIGITS; | ||||
| 	int feature_detected = 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 { | ||||
| 	} | ||||
| 	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); | ||||
| 	ast_rwlock_rdlock(&features_lock); | ||||
| 	for (x = 0; x < FEATURES_COUNT; x++) { | ||||
| 		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); | ||||
| 				feature_detected = 1; | ||||
| 				break; | ||||
| 			} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) { | ||||
| 				if (res == AST_FEATURE_RETURN_PASSDIGITS) | ||||
| 					res = AST_FEATURE_RETURN_STOREDIGITS; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	ast_rwlock_unlock(&features_lock); | ||||
|  | ||||
| 	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) { | ||||
| 	if (ast_strlen_zero(dynamic_features) || feature_detected) | ||||
| 		return res; | ||||
|  | ||||
| 	tmp = ast_strdupa(dynamic_features); | ||||
|  | ||||
| 	while ((tok = strsep(&tmp, "#"))) { | ||||
| 		AST_RWLIST_RDLOCK(&feature_groups); | ||||
|  | ||||
| 		fg = find_group(tok); | ||||
|  | ||||
| 		if (fg) { | ||||
| 			AST_LIST_TRAVERSE(&fg->features, fge, entry) { | ||||
| 				if (strcasecmp(fge->exten, code)) | ||||
| 					continue; | ||||
|  | ||||
| 				res = fge->feature->operation(chan, peer, config, code, sense, fge->feature); | ||||
| 				if (res != AST_FEATURE_RETURN_KEEPTRYING) { | ||||
| 					AST_RWLIST_UNLOCK(&feature_groups); | ||||
| 					break; | ||||
| 				} | ||||
| 		res = FEATURE_RETURN_PASSDIGITS; | ||||
| 				res = AST_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) { | ||||
| 			if (fge) | ||||
| 				break; | ||||
| 		} | ||||
| 		res = FEATURE_RETURN_PASSDIGITS; | ||||
|  | ||||
| 		AST_RWLIST_UNLOCK(&feature_groups); | ||||
|  | ||||
| 		AST_RWLIST_RDLOCK(&feature_list); | ||||
|  | ||||
| 		if (!(feature = find_dynamic_feature(tok))) { | ||||
| 			AST_RWLIST_UNLOCK(&feature_list); | ||||
| 			continue; | ||||
| 		} | ||||
| 			 | ||||
| 		/* Feature is up for consideration */ | ||||
| 		if (!strcmp(feature->exten, code)) { | ||||
| 			ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok); | ||||
| 			res = feature->operation(chan, peer, config, code, sense, feature); | ||||
| 			if (res != AST_FEATURE_RETURN_KEEPTRYING) { | ||||
| 				AST_RWLIST_UNLOCK(&feature_list); | ||||
| 				break; | ||||
| 			} | ||||
| 			res = AST_FEATURE_RETURN_PASSDIGITS; | ||||
| 		} else if (!strncmp(feature->exten, code, strlen(code))) | ||||
| 			res = AST_FEATURE_RETURN_STOREDIGITS; | ||||
|  | ||||
| 		AST_RWLIST_UNLOCK(&feature_list); | ||||
| 	} | ||||
| 	ast_features_unlock(); | ||||
| 	 | ||||
| 	return res; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user