app_queue: Enable set the wrapuptime from AddQueueMember application
authorRodrigo Ramírez Norambuena <a@rodrigoramirez.com>
Tue, 11 Dec 2018 14:15:01 +0000 (11:15 -0300)
committerJoshua C. Colp <jcolp@digium.com>
Tue, 19 Feb 2019 14:37:10 +0000 (08:37 -0600)
This change add ability to set the wrapuptime per-member using the
AddQueueMember application.

The feature to set wrapuptime per member was include in the issue
ASTERISK-27483 for static member by configuration file and was not
added to set from AddQueueMember.

ASTERISK-28055 #close

Change-Id: I7c7ee4a6f804922cd7c42cb02eea26eb3806c6cf

apps/app_queue.c

index 60be305..8b34d73 100644 (file)
                        <parameter name="options" />
                        <parameter name="membername" />
                        <parameter name="stateinterface" />
+                       <parameter name="wrapuptime" />
                </syntax>
                <description>
                        <para>Dynamically adds interface to an existing queue. If the interface is
                                                <enum name="1"/>
                                        </enumlist>
                                </parameter>
+                               <parameter name="Wrapuptime">
+                                       <para>The Wrapup Time of the queue member. If this value is set will override the wrapup time of queue.</para>
+                               </parameter>
                        </syntax>
                </managerEventInstance>
        </managerEvent>
@@ -2260,7 +2264,7 @@ static void queue_publish_member_blob(struct stasis_message_type *type, struct a
 
 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
 {
-       return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
+       return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i, s: i}",
                "Queue", q->name,
                "MemberName", mem->membername,
                "Interface", mem->interface,
@@ -2274,7 +2278,8 @@ static struct ast_json *queue_member_blob_create(struct call_queue *q, struct me
                "Status", mem->status,
                "Paused", mem->paused,
                "PausedReason", mem->reason_paused,
-               "Ringinuse", mem->ringinuse);
+               "Ringinuse", mem->ringinuse,
+               "Wrapuptime", mem->wrapuptime);
 }
 
 /*! \brief Check if members are available
@@ -2679,7 +2684,7 @@ static void destroy_queue_member_cb(void *obj)
 }
 
 /*! \brief allocate space for new queue member and set fields based on parameters passed */
-static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
+static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
 {
        struct member *cur;
 
@@ -2687,6 +2692,7 @@ static struct member *create_queue_member(const char *interface, const char *mem
                cur->ringinuse = ringinuse;
                cur->penalty = penalty;
                cur->paused = paused;
+               cur->wrapuptime = wrapuptime;
                if (paused) {
                        time(&cur->lastpause); /* Update time of last pause */
                }
@@ -3468,7 +3474,7 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct
 
        /* Create a new member */
        if (!found) {
-               if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
+               if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse, wrapuptime))) {
                        m->dead = 0;
                        m->realtime = 1;
                        ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
@@ -7260,14 +7266,15 @@ static void dump_queue_members(struct call_queue *pm_queue)
                        continue;
                }
 
-               ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s",
+               ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s;%d",
                        ast_str_strlen(value) ? "|" : "",
                        cur_member->interface,
                        cur_member->penalty,
                        cur_member->paused,
                        cur_member->membername,
                        cur_member->state_interface,
-                       cur_member->reason_paused);
+                       cur_member->reason_paused,
+                       cur_member->wrapuptime);
 
                ao2_ref(cur_member, -1);
        }
@@ -7344,7 +7351,7 @@ static int remove_from_queue(const char *queuename, const char *interface)
  * \retval RES_EXISTS queue exists but no members
  * \retval RES_OUT_OF_MEMORY queue exists but not enough memory to create member
 */
-static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused)
+static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused, int wrapuptime)
 {
        struct call_queue *q;
        struct member *new_member, *old_member;
@@ -7358,7 +7365,7 @@ static int add_to_queue(const char *queuename, const char *interface, const char
 
        ao2_lock(q);
        if ((old_member = interface_exists(q, interface)) == NULL) {
-               if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse))) {
+               if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse, wrapuptime))) {
                        new_member->dynamic = 1;
                        if (reason_paused) {
                                ast_copy_string(new_member->reason_paused, reason_paused, sizeof(new_member->reason_paused));
@@ -7750,6 +7757,8 @@ static void reload_queue_members(void)
        int penalty = 0;
        char *paused_tok;
        int paused = 0;
+       char *wrapuptime_tok;
+       int wrapuptime = 0;
        char *reason_paused;
        struct ast_db_entry *db_tree;
        struct ast_db_entry *entry;
@@ -7798,6 +7807,7 @@ static void reload_queue_members(void)
                        membername = strsep(&member, ";");
                        state_interface = strsep(&member, ";");
                        reason_paused = strsep(&member, ";");
+                       wrapuptime_tok = strsep(&member, ";");
 
                        if (!penalty_tok) {
                                ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
@@ -7819,10 +7829,18 @@ static void reload_queue_members(void)
                                break;
                        }
 
-                       ast_debug(1, "Reload Members: Queue: %s  Member: %s  Name: %s  Penalty: %d  Paused: %d ReasonPause: %s\n",
-                                     queue_name, interface, membername, penalty, paused, reason_paused);
+                       if (!ast_strlen_zero(wrapuptime_tok)) {
+                               wrapuptime = strtol(wrapuptime_tok, NULL, 10);
+                               if (errno == ERANGE) {
+                                       ast_log(LOG_WARNING, "Error converting wrapuptime: %s: Out of range.\n", wrapuptime_tok);
+                                       break;
+                               }
+                       }
+
+                       ast_debug(1, "Reload Members: Queue: %s  Member: %s  Name: %s  Penalty: %d  Paused: %d ReasonPause: %s  Wrapuptime: %d\n",
+                                     queue_name, interface, membername, penalty, paused, reason_paused, wrapuptime);
 
-                       if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface, reason_paused) == RES_OUTOFMEMORY) {
+                       if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface, reason_paused, wrapuptime) == RES_OUTOFMEMORY) {
                                ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
                                break;
                        }
@@ -7984,7 +8002,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, *temppos = NULL;
+       char *parse, *tmp, *temppos = NULL;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(queuename);
                AST_APP_ARG(interface);
@@ -7992,11 +8010,13 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
                AST_APP_ARG(options);
                AST_APP_ARG(membername);
                AST_APP_ARG(state_interface);
+               AST_APP_ARG(wrapuptime);
        );
        int penalty = 0;
+       int wrapuptime;
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]])\n");
+               ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
                return -1;
        }
 
@@ -8019,7 +8039,18 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
                }
        }
 
-       switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL)) {
+       if (!ast_strlen_zero(args.wrapuptime)) {
+               tmp = args.wrapuptime;
+               ast_strip(tmp);
+               wrapuptime = atoi(tmp);
+               if (wrapuptime < 0) {
+                       wrapuptime = 0;
+               }
+       } else {
+               wrapuptime = 0;
+       }
+
+       switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, 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", "");
@@ -9265,7 +9296,7 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
        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))) {
+       if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse, wrapuptime))) {
                newm->wrapuptime = wrapuptime;
                if (cur) {
                        /* Round Robin Queue Position must be copied if this is replacing an existing member */
@@ -10078,11 +10109,12 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
                                                "Status: %d\r\n"
                                                "Paused: %d\r\n"
                                                "PausedReason: %s\r\n"
+                                               "Wrapuptime: %d\r\n"
                                                "%s"
                                                "\r\n",
                                                q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
                                                mem->penalty, mem->calls, (int)mem->lastcall, (int)mem->lastpause, mem->starttime ? 1 : 0, mem->status,
-                                               mem->paused, mem->reason_paused, idText);
+                                               mem->paused, mem->reason_paused, mem->wrapuptime, idText);
                                        ++q_items;
                                }
                                ao2_ref(mem, -1);
@@ -10127,8 +10159,8 @@ 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;
-       int paused, penalty = 0;
+       const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface, *wrapuptime_s;
+       int paused, penalty, wrapuptime = 0;
 
        queuename = astman_get_header(m, "Queue");
        interface = astman_get_header(m, "Interface");
@@ -10136,6 +10168,7 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
        paused_s = astman_get_header(m, "Paused");
        membername = astman_get_header(m, "MemberName");
        state_interface = astman_get_header(m, "StateInterface");
+       wrapuptime_s = astman_get_header(m, "Wrapuptime");
 
        if (ast_strlen_zero(queuename)) {
                astman_send_error(s, m, "'Queue' not specified.");
@@ -10153,13 +10186,19 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
                penalty = 0;
        }
 
+       if (ast_strlen_zero(wrapuptime_s)) {
+               wrapuptime = 0;
+       } else if (sscanf(wrapuptime_s, "%30d", &wrapuptime) != 1 || wrapuptime < 0) {
+               wrapuptime = 0;
+       }
+
        if (ast_strlen_zero(paused_s)) {
                paused = 0;
        } else {
                paused = abs(ast_true(paused_s));
        }
 
-       switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, NULL)) {
+       switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, NULL, wrapuptime)) {
        case RES_OKAY:
                if (ast_strlen_zero(membername) || !log_membername_as_agent) {
                        ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
@@ -10509,7 +10548,7 @@ 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)) {
+       switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface, NULL, 0)) {
        case RES_OKAY:
                if (ast_strlen_zero(membername) || !log_membername_as_agent) {
                        ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");