mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +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;
							 | 
						||
| 
								 | 
							
								}
							 |