]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_queue: allow dynamically adding a queue member in paused state.
authorSperl Viktor <viktike32@gmail.com>
Wed, 27 Nov 2024 16:36:39 +0000 (17:36 +0100)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 23 Jan 2025 18:39:41 +0000 (18:39 +0000)
Fixes: #1007
UserNote: use the p option of AddQueueMember() for paused member state.
Optionally, use the r(reason) option to specify a custom reason for the pause.

(cherry picked from commit a80ae57cac1ee4ccab0a44c6cb45d1c184e5ca41)

apps/app_queue.c
configs/samples/queues.conf.sample

index b4d634576167f0271e7f6b0e0240e3e74e28878e..2053328a6f6788b5c7f942b3e199fa73aefda714 100644 (file)
                        <parameter name="queuename" required="true" />
                        <parameter name="interface" />
                        <parameter name="penalty" />
-                       <parameter name="options" />
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="p">
+                                               <para>Add queue member in paused state.</para>
+                                       </option>
+                                       <option name="r">
+                                               <argument name="reason" required="true" />
+                                               <para>Specify a reason why the member is in paused state.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
                        <parameter name="membername" />
                        <parameter name="stateinterface" />
                        <parameter name="wrapuptime" />
                        <parameter name="Paused">
                                <para>To pause or not the member initially (true/false or 1/0).</para>
                        </parameter>
+                       <parameter name="Reason" required="false">
+                               <para>Text description why the member is paused.</para>
+                       </parameter>
                        <parameter name="MemberName">
                                <para>Text alias for the interface.</para>
                        </parameter>
                        <parameter name="Paused" required="true">
                                <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
                        </parameter>
-                       <parameter name="Queue">
+                       <parameter name="Queue" required="false">
                                <para>The name of the queue in which to pause or unpause this member. If not specified, the member will be paused or unpaused in all the queues it is a member of.</para>
                        </parameter>
-                       <parameter name="Reason">
+                       <parameter name="Reason" required="false">
                                <para>Text description, returned in the event QueueMemberPaused.</para>
                        </parameter>
                </syntax>
@@ -1502,6 +1515,22 @@ AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
        AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
 END_OPTIONS);
 
+
+enum aqm_flags {
+       AQMFLAG_PAUSED = (1 << 1),
+       AQMFLAG_REASON = (1 << 2),
+};
+
+enum aqm_args {
+       AQM_OPT_ARG_PAUSE_REASON = 0,
+       AQM_OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
+};
+
+AST_APP_OPTIONS(aqm_opts, {
+       AST_APP_OPTION('p', AQMFLAG_PAUSED),
+       AST_APP_OPTION_ARG('r', AQMFLAG_REASON, AQM_OPT_ARG_PAUSE_REASON),
+});
+
 enum {
        QUEUE_STRATEGY_RINGALL = 0,
        QUEUE_STRATEGY_LEASTRECENT,
@@ -8354,7 +8383,7 @@ static int rqm_exec(struct ast_channel *chan, const char *data)
 static int aqm_exec(struct ast_channel *chan, const char *data)
 {
        int res=-1;
-       char *parse, *tmp, *temppos = NULL;
+       char *parse, *tmp, *temppos = NULL, *reason = NULL;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(queuename);
                AST_APP_ARG(interface);
@@ -8365,7 +8394,9 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
                AST_APP_ARG(wrapuptime);
        );
        int penalty = 0;
+       int paused = 0;
        int wrapuptime;
+       struct ast_flags flags = { 0 };
 
        if (ast_strlen_zero(data)) {
                ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
@@ -8376,6 +8407,17 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
 
        AST_STANDARD_APP_ARGS(args, parse);
 
+       if (args.options) {
+               char *opts[AQM_OPT_ARG_ARRAY_SIZE] = { NULL, };
+               ast_app_parse_options(aqm_opts, &flags, opts, args.options);
+               if (ast_test_flag(&flags, AQMFLAG_PAUSED)) {
+                       paused = 1;
+                       if (ast_test_flag(&flags, AQMFLAG_REASON) && !ast_strlen_zero(opts[AQM_OPT_ARG_PAUSE_REASON])) {
+                               reason = ast_strdupa(opts[AQM_OPT_ARG_PAUSE_REASON]);
+                       }
+               }
+       }
+
        if (ast_strlen_zero(args.interface)) {
                args.interface = ast_strdupa(ast_channel_name(chan));
                temppos = strrchr(args.interface, '-');
@@ -8402,7 +8444,7 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
                wrapuptime = 0;
        }
 
-       switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, wrapuptime)) {
+       switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, paused, queue_persistent_members, args.state_interface, reason, wrapuptime)) {
        case RES_OKAY:
                if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
                        ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
@@ -9623,6 +9665,7 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
        int penalty;
        int ringinuse;
        int wrapuptime;
+       int paused;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(interface);
                AST_APP_ARG(penalty);
@@ -9630,6 +9673,7 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
                AST_APP_ARG(state_interface);
                AST_APP_ARG(ringinuse);
                AST_APP_ARG(wrapuptime);
+               AST_APP_ARG(paused);
        );
 
        if (ast_strlen_zero(memberdata)) {
@@ -9695,11 +9739,30 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
                wrapuptime = 0;
        }
 
+       if (!ast_strlen_zero(args.paused)) {
+               tmp = args.paused;
+               ast_strip(tmp);
+               if (ast_true(tmp)) {
+                       paused = 1;
+               } else if (ast_false(tmp)) {
+                       paused = 0;
+               } else {
+                       ast_log(LOG_ERROR, "Member %s has an invalid paused value.\n", membername);
+                       paused = 0;
+               }
+       } else {
+               paused = 0;
+       }
+
        /* Find the old position in the list */
        ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
        cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
 
-       if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse, wrapuptime))) {
+       if (cur) {
+               paused = cur->paused;
+       }
+
+       if ((newm = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse, wrapuptime))) {
                newm->wrapuptime = wrapuptime;
                if (cur) {
                        ao2_lock(q->members);
@@ -10610,13 +10673,14 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
 
 static int manager_add_queue_member(struct mansession *s, const struct message *m)
 {
-       const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface, *wrapuptime_s;
+       const char *queuename, *interface, *penalty_s, *paused_s, *reason, *membername, *state_interface, *wrapuptime_s;
        int paused, penalty, wrapuptime = 0;
 
        queuename = astman_get_header(m, "Queue");
        interface = astman_get_header(m, "Interface");
        penalty_s = astman_get_header(m, "Penalty");
        paused_s = astman_get_header(m, "Paused");
+       reason = astman_get_header(m, "Reason");                          /* Optional */
        membername = astman_get_header(m, "MemberName");
        state_interface = astman_get_header(m, "StateInterface");
        wrapuptime_s = astman_get_header(m, "Wrapuptime");
@@ -10649,7 +10713,7 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
                paused = abs(ast_true(paused_s));
        }
 
-       switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, NULL, wrapuptime)) {
+       switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, reason, wrapuptime)) {
        case RES_OKAY:
                if (ast_strlen_zero(membername) || !log_membername_as_agent) {
                        ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
@@ -10989,21 +11053,21 @@ static int manager_request_withdraw_caller_from_queue(struct mansession *s, cons
 
 static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
-       int penalty;
+       const char *queuename, *interface, *membername = NULL, *state_interface = NULL, *reason = NULL;
+       int penalty, paused = 0;
 
        switch ( cmd ) {
        case CLI_INIT:
                e->command = "queue add member";
                e->usage =
-                       "Usage: queue add member <dial string> to <queue> [penalty <penalty> [as <membername> [state_interface <interface>]]]\n"
+                       "Usage: queue add member <dial string> to <queue> [penalty <penalty> [as <membername> [state_interface <interface> [paused <reason>]]]]\n"
                        "       Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally:  a penalty, membername and a state_interface\n";
                return NULL;
        case CLI_GENERATE:
                return complete_queue_add_member(a->line, a->word, a->pos, a->n);
        }
 
-       if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
+       if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12) && (a->argc != 14)) {
                return CLI_SHOWUSAGE;
        } else if (strcmp(a->argv[4], "to")) {
                return CLI_SHOWUSAGE;
@@ -11013,6 +11077,8 @@ static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct as
                return CLI_SHOWUSAGE;
        } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
                return CLI_SHOWUSAGE;
+       } else if ((a->argc == 14) && strcmp(a->argv[12], "paused")) {
+               return CLI_SHOWUSAGE;
        }
 
        queuename = a->argv[5];
@@ -11039,7 +11105,12 @@ static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct as
                state_interface = a->argv[11];
        }
 
-       switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface, NULL, 0)) {
+       if (a->argc >= 14) {
+               paused = 1;
+               reason = a->argv[13];
+       }
+
+       switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, reason, 0)) {
        case RES_OKAY:
                if (ast_strlen_zero(membername) || !log_membername_as_agent) {
                        ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
index 4207a01e2d7c0f5875ceee1b751944ab979d4c7d..1b853eee6cef91e356791bb3d15bf13ef391b3f1 100644 (file)
@@ -548,12 +548,12 @@ monitor-type = MixMonitor
 ; must also preload pbx_config.so and chan_local.so (or pbx_ael.so, pbx_lua.so,
 ; or pbx_realtime.so, depending on how your dialplan is configured).
 ;
-; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse][,wrapuptime]
+; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse][,wrapuptime][,paused]
 ;
 ;member => DAHDI/1
 ;member => DAHDI/2,10
 ;member => DAHDI/3,10,Bob Johnson
 ;member => Local/1001@agents,0,May Flowers,Agent:1001
 ;member => Local/1002@agents,0,John Doe,Agent:1002
-;member => Local/1000@default,0,John Smith,SIP/1000
-;member => Local/2000@default,0,Lorem Ipsum,SIP/2000,no
+;member => Local/1000@default,0,John Smith,PJSIP/1000
+;member => Local/2000@default,0,Lorem Ipsum,PJSIP/2000,no