func_pjsip_endpoint: Add PJSIP_ENDPOINT function for querying endpoint details
[asterisk/asterisk.git] / funcs / func_timeout.c
index 58b78c1..3c2810f 100644 (file)
  * \ingroup functions
  */
 
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
-#include "asterisk/logger.h"
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
-#include "asterisk/options.h"
+
+/*** 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
+                               are: <literal>absolute</literal>, <literal>digit</literal> or 
+                               <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>
+ ***/
 
 static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
                        char *buf, size_t len)
 {
-       time_t myt;
+       struct timeval myt;
 
        if (!chan)
                return -1;
@@ -57,31 +90,31 @@ static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
        switch (*data) {
        case 'a':
        case 'A':
-               if (chan->whentohangup == 0) {
+               if (ast_tvzero(*ast_channel_whentohangup(chan))) {
                        ast_copy_string(buf, "0", len);
                } else {
-                       time(&myt);
-                       snprintf(buf, len, "%d", (int) (chan->whentohangup - myt));
+                       myt = ast_tvnow();
+                       snprintf(buf, len, "%.3f", ast_tvdiff_ms(*ast_channel_whentohangup(chan), myt) / 1000.0);
                }
                break;
 
        case 'r':
        case 'R':
-               if (chan->pbx) {
-                       snprintf(buf, len, "%d", chan->pbx->rtimeout);
+               if (ast_channel_pbx(chan)) {
+                       snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->rtimeoutms / 1000.0);
                }
                break;
 
        case 'd':
        case 'D':
-               if (chan->pbx) {
-                       snprintf(buf, len, "%d", chan->pbx->dtimeout);
+               if (ast_channel_pbx(chan)) {
+                       snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->dtimeoutms / 1000.0);
                }
                break;
 
        default:
                ast_log(LOG_ERROR, "Unknown timeout type specified.\n");
-               break;
+               return -1;
        }
 
        return 0;
@@ -90,9 +123,12 @@ static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
 static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
                         const char *value)
 {
-       int x;
+       double x = 0.0;
+       long sec = 0L;
        char timestr[64];
        struct ast_tm myt;
+       struct timeval when = {0,};
+       int res;
 
        if (!chan)
                return -1;
@@ -105,37 +141,44 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
        if (!value)
                return -1;
 
-       x = atoi(value);
-       if (x < 0)
-               x = 0;
+       res = sscanf(value, "%30ld%30lf", &sec, &x);
+       if (res == 0 || sec < 0) {
+               when.tv_sec = 0;
+               when.tv_usec = 0;
+       } else if (res == 1) {
+               when.tv_sec = sec;
+       } else if (res == 2) {
+               when.tv_sec = sec;
+               when.tv_usec = x * 1000000;
+       }
 
        switch (*data) {
        case 'a':
        case 'A':
-               ast_channel_setwhentohangup(chan, x);
-                       if (chan->whentohangup) {
-                               struct timeval tv = { chan->whentohangup, 0 };
-                               ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",
-                                       ast_localtime(&tv, &myt, NULL));
+               ast_channel_setwhentohangup_tv(chan, when);
+               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 {
+               } else {
                        ast_verb(3, "Channel hangup cancelled.\n");
-                       }
+               }
                break;
 
        case 'r':
        case 'R':
-               if (chan->pbx) {
-                       chan->pbx->rtimeout = x;
-                       ast_verb(3, "Response timeout set to %d\n", chan->pbx->rtimeout);
+               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);
                }
                break;
 
        case 'd':
        case 'D':
-               if (chan->pbx) {
-                       chan->pbx->dtimeout = x;
-                       ast_verb(3, "Digit timeout set to %d\n", chan->pbx->dtimeout);
+               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);
                }
                break;
 
@@ -149,30 +192,8 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function timeout_function = {
        .name = "TIMEOUT",
-       .synopsis = "Gets or sets timeouts on the channel. Timeout values are in seconds.",
-       .syntax = "TIMEOUT(timeouttype)",
-       .desc =
-               "Gets or sets various channel timeouts. The timeouts that can be\n"
-               "manipulated are:\n" "\n"
-               "absolute: The absolute maximum amount of time permitted for a call.  A\n"
-               "          setting of 0 disables the timeout.\n" "\n"
-               "digit:    The maximum amount of time permitted between digits when the\n"
-               "          user is typing in an extension.  When this timeout expires,\n"
-               "          after the user has started to type in an extension, the\n"
-               "          extension will be considered complete, and will be\n"
-               "          interpreted.  Note that if an extension typed in is valid,\n"
-               "          it will not have to timeout to be tested, so typically at\n"
-               "          the expiry of this timeout, the extension will be considered\n"
-               "          invalid (and thus control would be passed to the 'i'\n"
-               "          extension, or if it doesn't exist the call would be\n"
-               "          terminated).  The default timeout is 5 seconds.\n" "\n"
-               "response: The maximum amount of time permitted after falling through a\n"
-               "          series of priorities for a channel in which the user may\n"
-               "          begin typing an extension.  If the user does not type an\n"
-               "          extension in this amount of time, control will pass to the\n"
-               "          't' extension if it exists, and if not the call would be\n"
-               "          terminated.  The default timeout is 10 seconds.\n",
        .read = timeout_read,
+       .read_max = 22,
        .write = timeout_write,
 };