| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  |  * Copyright (C) 1999 - 2006, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Channel timeout related dialplan functions | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2007-01-24 09:05:29 +00:00
										 |  |  |  * \ingroup functions | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-14 20:28:54 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/app.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | /*** DOCUMENTATION
 | 
					
						
							|  |  |  | 	<function name="TIMEOUT" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Gets or sets timeouts on the channel. Timeout values are in seconds. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<parameter name="timeouttype" required="true"> | 
					
						
							|  |  |  | 				<para>The timeout that will be manipulated. The possible timeout types | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  | 				are: <literal>absolute</literal>, <literal>digit</literal> or | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | 				<literal>response</literal></para> | 
					
						
							|  |  |  | 			</parameter> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 			<para>The timeouts that can be manipulated are:</para> | 
					
						
							|  |  |  | 			<para><literal>absolute</literal>: The absolute maximum amount of time permitted for a call. | 
					
						
							|  |  |  | 			Setting of 0 disables the timeout.</para> | 
					
						
							|  |  |  | 			<para><literal>digit</literal>: The maximum amount of time permitted between digits when the | 
					
						
							|  |  |  | 			user is typing in an extension.  When this timeout expires, | 
					
						
							|  |  |  | 			after the user has started to type in an extension, the | 
					
						
							|  |  |  | 			extension will be considered complete, and will be | 
					
						
							|  |  |  | 			interpreted.  Note that if an extension typed in is valid, | 
					
						
							|  |  |  | 			it will not have to timeout to be tested, so typically at | 
					
						
							|  |  |  | 			the expiry of this timeout, the extension will be considered | 
					
						
							|  |  |  | 			invalid (and thus control would be passed to the <literal>i</literal> | 
					
						
							|  |  |  | 			extension, or if it doesn't exist the call would be | 
					
						
							|  |  |  | 			terminated).  The default timeout is 5 seconds.</para> | 
					
						
							|  |  |  | 			<para><literal>response</literal>: The maximum amount of time permitted after falling through a | 
					
						
							|  |  |  | 			series of priorities for a channel in which the user may | 
					
						
							|  |  |  | 			begin typing an extension.  If the user does not type an | 
					
						
							|  |  |  | 			extension in this amount of time, control will pass to the | 
					
						
							|  |  |  | 			<literal>t</literal> extension if it exists, and if not the call would be | 
					
						
							|  |  |  | 			terminated.  The default timeout is 10 seconds.</para> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</function> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-06 00:13:33 +00:00
										 |  |  | static int timeout_read(struct ast_channel *chan, const char *cmd, char *data, | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 			char *buf, size_t len) | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-01 23:06:23 +00:00
										 |  |  | 	struct timeval myt; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-19 02:51:21 +00:00
										 |  |  | 	if (!chan) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2006-09-28 18:09:01 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Must specify type of timeout to get.\n"); | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (*data) { | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	case 'a': | 
					
						
							|  |  |  | 	case 'A': | 
					
						
							| 
									
										
										
										
											2012-02-29 16:52:47 +00:00
										 |  |  | 		if (ast_tvzero(*ast_channel_whentohangup(chan))) { | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 			ast_copy_string(buf, "0", len); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-05-01 23:06:23 +00:00
										 |  |  | 			myt = ast_tvnow(); | 
					
						
							| 
									
										
										
										
											2012-02-29 16:52:47 +00:00
										 |  |  | 			snprintf(buf, len, "%.3f", ast_tvdiff_ms(*ast_channel_whentohangup(chan), myt) / 1000.0); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 'r': | 
					
						
							|  |  |  | 	case 'R': | 
					
						
							| 
									
										
										
										
											2012-02-20 23:43:27 +00:00
										 |  |  | 		if (ast_channel_pbx(chan)) { | 
					
						
							|  |  |  | 			snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->rtimeoutms / 1000.0); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 'd': | 
					
						
							|  |  |  | 	case 'D': | 
					
						
							| 
									
										
										
										
											2012-02-20 23:43:27 +00:00
										 |  |  | 		if (ast_channel_pbx(chan)) { | 
					
						
							|  |  |  | 			snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->dtimeoutms / 1000.0); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2006-09-28 18:09:01 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unknown timeout type specified.\n"); | 
					
						
							| 
									
										
										
										
											2008-10-06 21:09:05 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-06 00:13:33 +00:00
										 |  |  | static int timeout_write(struct ast_channel *chan, const char *cmd, char *data, | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 			 const char *value) | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-22 16:07:59 +00:00
										 |  |  | 	double x = 0.0; | 
					
						
							|  |  |  | 	long sec = 0L; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	char timestr[64]; | 
					
						
							| 
									
										
										
										
											2007-07-18 19:47:20 +00:00
										 |  |  | 	struct ast_tm myt; | 
					
						
							| 
									
										
										
										
											2008-12-22 16:07:59 +00:00
										 |  |  | 	struct timeval when = {0,}; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-19 02:51:21 +00:00
										 |  |  | 	if (!chan) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2006-09-28 18:09:01 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Must specify type of timeout to set.\n"); | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	if (!value) | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	res = sscanf(value, "%30ld%30lf", &sec, &x); | 
					
						
							| 
									
										
										
										
											2008-12-22 16:07:59 +00:00
										 |  |  | 	if (res == 0 || sec < 0) { | 
					
						
							| 
									
										
										
										
											2008-08-07 01:07:40 +00:00
										 |  |  | 		when.tv_sec = 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 16:07:59 +00:00
										 |  |  | 		when.tv_usec = 0; | 
					
						
							|  |  |  | 	} else if (res == 1) { | 
					
						
							|  |  |  | 		when.tv_sec = sec; | 
					
						
							|  |  |  | 	} else if (res == 2) { | 
					
						
							| 
									
										
										
										
											2008-08-07 01:07:40 +00:00
										 |  |  | 		when.tv_sec = sec; | 
					
						
							|  |  |  | 		when.tv_usec = x * 1000000; | 
					
						
							| 
									
										
										
										
											2008-05-15 10:56:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 	switch (*data) { | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	case 'a': | 
					
						
							|  |  |  | 	case 'A': | 
					
						
							| 
									
										
										
										
											2013-12-18 20:33:37 +00:00
										 |  |  | 		ast_channel_lock(chan); | 
					
						
							| 
									
										
										
										
											2008-08-07 01:07:40 +00:00
										 |  |  | 		ast_channel_setwhentohangup_tv(chan, when); | 
					
						
							| 
									
										
										
										
											2013-12-18 20:33:37 +00:00
										 |  |  | 		ast_channel_unlock(chan); | 
					
						
							| 
									
										
										
										
											2014-01-14 18:14:02 +00:00
										 |  |  | 		if (VERBOSITY_ATLEAST(3)) { | 
					
						
							|  |  |  | 			if (!ast_tvzero(*ast_channel_whentohangup(chan))) { | 
					
						
							|  |  |  | 				when = ast_tvadd(when, ast_tvnow()); | 
					
						
							|  |  |  | 				ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z", | 
					
						
							|  |  |  | 					ast_localtime(&when, &myt, NULL)); | 
					
						
							|  |  |  | 				ast_verb(3, "Channel will hangup at %s.\n", timestr); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ast_verb(3, "Channel hangup cancelled.\n"); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2007-12-14 15:59:09 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 'r': | 
					
						
							|  |  |  | 	case 'R': | 
					
						
							| 
									
										
										
										
											2012-02-20 23:43:27 +00:00
										 |  |  | 		if (ast_channel_pbx(chan)) { | 
					
						
							|  |  |  | 			ast_channel_pbx(chan)->rtimeoutms = when.tv_sec * 1000 + when.tv_usec / 1000; | 
					
						
							|  |  |  | 			ast_verb(3, "Response timeout set to %.3f\n", ast_channel_pbx(chan)->rtimeoutms / 1000.0); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case 'd': | 
					
						
							|  |  |  | 	case 'D': | 
					
						
							| 
									
										
										
										
											2012-02-20 23:43:27 +00:00
										 |  |  | 		if (ast_channel_pbx(chan)) { | 
					
						
							|  |  |  | 			ast_channel_pbx(chan)->dtimeoutms = when.tv_sec * 1000 + when.tv_usec / 1000; | 
					
						
							|  |  |  | 			ast_verb(3, "Digit timeout set to %.3f\n", ast_channel_pbx(chan)->dtimeoutms / 1000.0); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2006-09-28 18:09:01 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unknown timeout type specified.\n"); | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | static struct ast_custom_function timeout_function = { | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | 	.name = "TIMEOUT", | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | 	.read = timeout_read, | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 	.read_max = 22, | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | 	.write = timeout_write, | 
					
						
							| 
									
										
										
										
											2005-05-15 17:45:30 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 	return ast_custom_function_unregister(&timeout_function); | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 	return ast_custom_function_register(&timeout_function); | 
					
						
							| 
									
										
										
										
											2006-02-11 03:14:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel timeout dialplan functions"); |