Merge "AST-2018-005: Fix tdata leaks when calling pjsip_endpt_send_response(2)"
[asterisk/asterisk.git] / apps / app_channelredirect.c
index de8b6ab..4f3b791 100644 (file)
  * \ingroup applications
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include "asterisk/file.h"
-#include "asterisk/logger.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
@@ -41,21 +37,37 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/features.h"
 
-static char *tdesc = "Channel Redirect";
-static char *app = "ChannelRedirect";
-static char *synopsis = "Redirects given channel to a dialplan target.";
-static char *descrip = 
-"ChannelRedirect(channel|[[context|]extension|]priority):\n"
-"  Sends the specified channel to the specified extension priority\n";
-
-LOCAL_USER_DECL;
-
-static int asyncgoto_exec(struct ast_channel *chan, void *data)
+/*** DOCUMENTATION
+       <application name="ChannelRedirect" language="en_US">
+               <synopsis>
+                       Redirects given channel to a dialplan target
+               </synopsis>
+               <syntax>
+                       <parameter name="channel" required="true" />
+                       <parameter name="context" required="false" />
+                       <parameter name="extension" required="false" />
+                       <parameter name="priority" required="true" />
+               </syntax>
+               <description>
+                       <para>Sends the specified channel to the specified extension priority</para>
+
+                       <para>This application sets the following channel variables upon completion</para>
+                       <variablelist>
+                               <variable name="CHANNELREDIRECT_STATUS">
+                                       <value name="NOCHANNEL" />
+                                       <value name="SUCCESS" />
+                                       <para>Are set to the result of the redirection</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
+static const char app[] = "ChannelRedirect";
+
+static int asyncgoto_exec(struct ast_channel *chan, const char *data)
 {
        int res = -1;
-       struct localuser *u;
-       char *info, *context, *exten, *priority;
-       int prio = 1;
+       char *info;
        struct ast_channel *chan2 = NULL;
 
        AST_DECLARE_APP_ARGS(args,
@@ -64,93 +76,42 @@ static int asyncgoto_exec(struct ast_channel *chan, void *data)
        );
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
+               ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
                return -1;
        }
 
-       LOCAL_USER_ADD(u);
-
        info = ast_strdupa(data);
        AST_STANDARD_APP_ARGS(args, info);
 
        if (ast_strlen_zero(args.channel) || ast_strlen_zero(args.label)) {
-               ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
-               goto quit;
+               ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
+               return -1;
        }
 
-       chan2 = ast_get_channel_by_name_locked(args.channel);
-       if (!chan2) {
+       if (!(chan2 = ast_channel_get_by_name(args.channel))) {
                ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
-               goto quit;
-       }
-
-       /* Parsed right to left, so standard parsing won't work */
-       context = strsep(&args.label, "|");
-       exten = strsep(&args.label, "|");
-       if (exten) {
-               priority = strsep(&args.label, "|");
-               if (!priority) {
-                       priority = exten;
-                       exten = context;
-                       context = NULL;
-               }
-       } else {
-               priority = context;
-               context = NULL;
-       }
-
-       if (!(prio = ast_findlabel_extension(chan2, S_OR(context, chan2->context), S_OR(exten, chan2->exten),
-                                            priority, chan2->cid.cid_num))) {
-               ast_log(LOG_WARNING, "'%s' is not a known priority or label\n", priority);
-               goto chanquit;
+               pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "NOCHANNEL");
+               return 0;
        }
 
-       ast_log(LOG_DEBUG, "Attempting async goto (%s) to %s\n", args.channel, args.label);
+       res = ast_async_parseable_goto(chan2, args.label);
 
-       if (ast_async_goto_if_exists(chan2, context ? context : chan2->context, exten ? exten : chan2->exten, prio))
-               ast_log(LOG_WARNING, "%s failed for %s\n", app, args.channel);
-       else
-               res = 0;
+       chan2 = ast_channel_unref(chan2);
 
- chanquit:
-       ast_mutex_unlock(&chan2->lock);
- quit:
-       LOCAL_USER_REMOVE(u);
+       pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "SUCCESS");
 
        return res;
 }
 
-int unload_module(void)
+static int unload_module(void)
 {
-       int res;
-
-       res = ast_unregister_application(app);
-
-       STANDARD_HANGUP_LOCALUSERS;
-
-       return res;     
+       return ast_unregister_application(app);
 }
 
-int load_module(void)
+static int load_module(void)
 {
-       return ast_register_application(app, asyncgoto_exec, synopsis, descrip);
+       return ast_register_application_xml(app, asyncgoto_exec) ?
+               AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
-char *description(void)
-{
-       return tdesc;
-}
-
-int usecount(void)
-{
-       int res;
-
-       STANDARD_USECOUNT(res);
-
-       return res;
-}
-
-char *key()
-{
-       return ASTERISK_GPL_KEY;
-}
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirects a given channel to a dialplan target");