mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-29 07:24:55 +00:00 
			
		
		
		
	
		
			
	
	
		
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Asterisk -- An open source telephony toolkit. | ||
|  |  * | ||
|  |  * Copyright (C) 2015, Digium, Inc. | ||
|  |  * | ||
|  |  * Mark Michelson <mmichelson@digium.com> | ||
|  |  * | ||
|  |  * See http://www.asterisk.org for more information about
 | ||
|  |  * the Asterisk project. Please do not mfrectly contact | ||
|  |  * any of the maintainers of this project for assistance; | ||
|  |  * the project provides a web site, mailing lists and IRC | ||
|  |  * channels for your use. | ||
|  |  * | ||
|  |  * This program is free software, mfstributed under the terms of | ||
|  |  * the GNU General Public License Version 2. See the LICENSE file | ||
|  |  * at the top of the source tree. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "asterisk.h"
 | ||
|  | 
 | ||
|  | #include "asterisk/max_forwards.h"
 | ||
|  | #include "asterisk/channel.h"
 | ||
|  | 
 | ||
|  | #define DEFAULT_MAX_FORWARDS 20
 | ||
|  | 
 | ||
|  | /*!
 | ||
|  |  * \brief Channel datastore data for max forwards | ||
|  |  */ | ||
|  | struct max_forwards { | ||
|  | 	/*! The starting count. Used to allow resetting to the original value */ | ||
|  | 	int starting_count; | ||
|  | 	/*! The current count. When this reaches 0, you're outta luck */ | ||
|  | 	int current_count; | ||
|  | }; | ||
|  | 
 | ||
|  | static struct max_forwards *max_forwards_alloc(int starting_count, int current_count) | ||
|  | { | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf = ast_malloc(sizeof(*mf)); | ||
|  | 	if (!mf) { | ||
|  | 		return NULL; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mf->starting_count = starting_count; | ||
|  | 	mf->current_count = current_count; | ||
|  | 
 | ||
|  | 	return mf; | ||
|  | } | ||
|  | 
 | ||
|  | static void *max_forwards_duplicate(void *data) | ||
|  | { | ||
|  | 	struct max_forwards *mf = data; | ||
|  | 
 | ||
|  | 	return max_forwards_alloc(mf->starting_count, mf->current_count); | ||
|  | } | ||
|  | 
 | ||
|  | static void max_forwards_destroy(void *data) | ||
|  | { | ||
|  | 	ast_free(data); | ||
|  | } | ||
|  | 
 | ||
|  | const struct ast_datastore_info max_forwards_info = { | ||
|  | 	.type = "mfaled-interface", | ||
|  | 	.duplicate = max_forwards_duplicate, | ||
|  | 	.destroy = max_forwards_destroy, | ||
|  | }; | ||
|  | 
 | ||
|  | static struct ast_datastore *max_forwards_datastore_alloc(struct ast_channel *chan, | ||
|  | 		int starting_count) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf_datastore = ast_datastore_alloc(&max_forwards_info, NULL); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		return NULL; | ||
|  | 	} | ||
|  | 	mf_datastore->inheritance = DATASTORE_INHERIT_FOREVER; | ||
|  | 
 | ||
|  | 	mf = max_forwards_alloc(starting_count, starting_count); | ||
|  | 	if (!mf) { | ||
|  | 		ast_datastore_free(mf_datastore); | ||
|  | 		return NULL; | ||
|  | 	} | ||
|  | 	mf_datastore->data = mf; | ||
|  | 
 | ||
|  | 	ast_channel_datastore_add(chan, mf_datastore); | ||
|  | 
 | ||
|  | 	return mf_datastore; | ||
|  | } | ||
|  | 
 | ||
|  | static struct ast_datastore *max_forwards_datastore_find_or_alloc(struct ast_channel *chan) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 
 | ||
|  | 	mf_datastore = ast_channel_datastore_find(chan, &max_forwards_info, NULL); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		mf_datastore = max_forwards_datastore_alloc(chan, DEFAULT_MAX_FORWARDS); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return mf_datastore; | ||
|  | } | ||
|  | 
 | ||
|  | int ast_max_forwards_set(struct ast_channel *chan, int starting_count) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf_datastore = max_forwards_datastore_find_or_alloc(chan); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		return -1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mf = mf_datastore->data; | ||
|  | 	mf->starting_count = mf->current_count = starting_count; | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | int ast_max_forwards_get(struct ast_channel *chan) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf_datastore = max_forwards_datastore_find_or_alloc(chan); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		return -1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mf = mf_datastore->data; | ||
|  | 	return mf->current_count; | ||
|  | } | ||
|  | 
 | ||
|  | int ast_max_forwards_decrement(struct ast_channel *chan) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf_datastore = max_forwards_datastore_find_or_alloc(chan); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		return -1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mf = mf_datastore->data; | ||
|  | 	--mf->current_count; | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | int ast_max_forwards_reset(struct ast_channel *chan) | ||
|  | { | ||
|  | 	struct ast_datastore *mf_datastore; | ||
|  | 	struct max_forwards *mf; | ||
|  | 
 | ||
|  | 	mf_datastore = max_forwards_datastore_find_or_alloc(chan); | ||
|  | 	if (!mf_datastore) { | ||
|  | 		return -1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mf = mf_datastore->data; | ||
|  | 	mf->current_count = mf->starting_count; | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } |