mirror of https://github.com/asterisk/asterisk
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							166 lines
						
					
					
						
							3.6 KiB
						
					
					
				
			
		
		
	
	
							166 lines
						
					
					
						
							3.6 KiB
						
					
					
				| /*
 | |
|  * 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;
 | |
| }
 |