diff --git a/apps/app_queue.c b/apps/app_queue.c index 92c49b5c38..9b1f486711 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -319,6 +319,7 @@ + Dynamically adds interface to an existing queue. If the interface is @@ -1108,6 +1109,9 @@ + + The Wrapup Time of the queue member. If this value is set will override the wrapup time of queue. + @@ -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", "");