Thu Apr 28 2011 16:56:47

Asterisk developer's documentation


func_timeout.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Channel timeout related dialplan functions
00022  *
00023  * \author Mark Spencer <markster@digium.com> 
00024  * \ingroup functions
00025  */
00026 
00027 #include "asterisk.h"
00028 
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211580 $")
00030 
00031 #include "asterisk/module.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/utils.h"
00035 #include "asterisk/app.h"
00036 
00037 /*** DOCUMENTATION
00038    <function name="TIMEOUT" language="en_US">
00039       <synopsis>
00040          Gets or sets timeouts on the channel. Timeout values are in seconds.
00041       </synopsis>
00042       <syntax>
00043          <parameter name="timeouttype" required="true">
00044             <para>The timeout that will be manipulated. The possible timeout types
00045             are: <literal>absolute</literal>, <literal>digit</literal> or 
00046             <literal>response</literal></para>
00047          </parameter>
00048       </syntax>
00049       <description>
00050          <para>The timeouts that can be manipulated are:</para>
00051          <para><literal>absolute</literal>: The absolute maximum amount of time permitted for a call.
00052          Setting of 0 disables the timeout.</para>
00053          <para><literal>digit</literal>: The maximum amount of time permitted between digits when the
00054          user is typing in an extension.  When this timeout expires,
00055          after the user has started to type in an extension, the
00056          extension will be considered complete, and will be
00057          interpreted.  Note that if an extension typed in is valid,
00058          it will not have to timeout to be tested, so typically at
00059          the expiry of this timeout, the extension will be considered
00060          invalid (and thus control would be passed to the <literal>i</literal>
00061          extension, or if it doesn't exist the call would be
00062          terminated).  The default timeout is 5 seconds.</para>
00063          <para><literal>response</literal>: The maximum amount of time permitted after falling through a
00064          series of priorities for a channel in which the user may
00065          begin typing an extension.  If the user does not type an
00066          extension in this amount of time, control will pass to the
00067          <literal>t</literal> extension if it exists, and if not the call would be
00068          terminated.  The default timeout is 10 seconds.</para>
00069       </description>
00070    </function>
00071  ***/
00072 
00073 static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
00074          char *buf, size_t len)
00075 {
00076    struct timeval myt;
00077 
00078    if (!chan)
00079       return -1;
00080 
00081    if (!data) {
00082       ast_log(LOG_ERROR, "Must specify type of timeout to get.\n");
00083       return -1;
00084    }
00085 
00086    switch (*data) {
00087    case 'a':
00088    case 'A':
00089       if (ast_tvzero(chan->whentohangup)) {
00090          ast_copy_string(buf, "0", len);
00091       } else {
00092          myt = ast_tvnow();
00093          snprintf(buf, len, "%.3f", ast_tvdiff_ms(chan->whentohangup, myt) / 1000.0);
00094       }
00095       break;
00096 
00097    case 'r':
00098    case 'R':
00099       if (chan->pbx) {
00100          snprintf(buf, len, "%.3f", chan->pbx->rtimeoutms / 1000.0);
00101       }
00102       break;
00103 
00104    case 'd':
00105    case 'D':
00106       if (chan->pbx) {
00107          snprintf(buf, len, "%.3f", chan->pbx->dtimeoutms / 1000.0);
00108       }
00109       break;
00110 
00111    default:
00112       ast_log(LOG_ERROR, "Unknown timeout type specified.\n");
00113       return -1;
00114    }
00115 
00116    return 0;
00117 }
00118 
00119 static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
00120           const char *value)
00121 {
00122    double x = 0.0;
00123    long sec = 0L;
00124    char timestr[64];
00125    struct ast_tm myt;
00126    struct timeval when = {0,};
00127    int res;
00128 
00129    if (!chan)
00130       return -1;
00131 
00132    if (!data) {
00133       ast_log(LOG_ERROR, "Must specify type of timeout to set.\n");
00134       return -1;
00135    }
00136 
00137    if (!value)
00138       return -1;
00139 
00140    res = sscanf(value, "%30ld%30lf", &sec, &x);
00141    if (res == 0 || sec < 0) {
00142       when.tv_sec = 0;
00143       when.tv_usec = 0;
00144    } else if (res == 1) {
00145       when.tv_sec = sec;
00146    } else if (res == 2) {
00147       when.tv_sec = sec;
00148       when.tv_usec = x * 1000000;
00149    }
00150 
00151    switch (*data) {
00152    case 'a':
00153    case 'A':
00154       ast_channel_setwhentohangup_tv(chan, when);
00155       if (VERBOSITY_ATLEAST(3)) {
00156          if (!ast_tvzero(chan->whentohangup)) {
00157             when = ast_tvadd(when, ast_tvnow());
00158             ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",
00159                ast_localtime(&when, &myt, NULL));
00160             ast_verbose("Channel will hangup at %s.\n", timestr);
00161          } else {
00162             ast_verbose("Channel hangup cancelled.\n");
00163          }
00164       }
00165       break;
00166 
00167    case 'r':
00168    case 'R':
00169       if (chan->pbx) {
00170          chan->pbx->rtimeoutms = when.tv_sec * 1000 + when.tv_usec / 1000.0;
00171          ast_verb(3, "Response timeout set to %.3f\n", chan->pbx->rtimeoutms / 1000.0);
00172       }
00173       break;
00174 
00175    case 'd':
00176    case 'D':
00177       if (chan->pbx) {
00178          chan->pbx->dtimeoutms = when.tv_sec * 1000 + when.tv_usec / 1000.0;
00179          ast_verb(3, "Digit timeout set to %.3f\n", chan->pbx->dtimeoutms / 1000.0);
00180       }
00181       break;
00182 
00183    default:
00184       ast_log(LOG_ERROR, "Unknown timeout type specified.\n");
00185       break;
00186    }
00187 
00188    return 0;
00189 }
00190 
00191 static struct ast_custom_function timeout_function = {
00192    .name = "TIMEOUT",
00193    .read = timeout_read,
00194    .write = timeout_write,
00195 };
00196 
00197 static int unload_module(void)
00198 {
00199    return ast_custom_function_unregister(&timeout_function);
00200 }
00201 
00202 static int load_module(void)
00203 {
00204    return ast_custom_function_register(&timeout_function);
00205 }
00206 
00207 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel timeout dialplan functions");