Merge mjohnston's pause/unpause (bug #3252)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4861 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
ffe9f7562c
commit
ffc1132528
1 changed files with 247 additions and 22 deletions
271
apps/app_queue.c
271
apps/app_queue.c
|
@ -148,6 +148,30 @@ static char *app_rqm_descrip =
|
||||||
"Example: RemoveQueueMember(techsupport|SIP/3000)\n"
|
"Example: RemoveQueueMember(techsupport|SIP/3000)\n"
|
||||||
"";
|
"";
|
||||||
|
|
||||||
|
static char *app_pqm = "PauseQueueMember" ;
|
||||||
|
static char *app_pqm_synopsis = "Pauses a queue member" ;
|
||||||
|
static char *app_pqm_descrip =
|
||||||
|
" PauseQueueMember([queuename]|interface):\n"
|
||||||
|
"Pauses (blocks calls for) a queue member.\n"
|
||||||
|
"The given interface will be paused in the given queue. This prevents\n"
|
||||||
|
"any calls from being sent from the queue to the interface until it is\n"
|
||||||
|
"unpaused with UnpauseQueueMember or the manager interface. If no\n"
|
||||||
|
"queuename is given, the interface is paused in every queue it is a\n"
|
||||||
|
"member of. If the interface is not in the named queue, or if no queue\n"
|
||||||
|
"is given and the interface is not in any queue, it will jump to\n"
|
||||||
|
" priority n+101, if it exists. Returns -1 if the interface is not\n"
|
||||||
|
"found and no extension to jump to exists, 0 otherwise.\n"
|
||||||
|
"Example: PauseQueueMember(|SIP/3000)\n";
|
||||||
|
|
||||||
|
static char *app_upqm = "UnpauseQueueMember" ;
|
||||||
|
static char *app_upqm_synopsis = "Unpauses a queue member" ;
|
||||||
|
static char *app_upqm_descrip =
|
||||||
|
" UnpauseQueueMember([queuename]|interface):\n"
|
||||||
|
"Unpauses (resumes calls to) a queue member.\n"
|
||||||
|
"This is the counterpart to PauseQueueMember and operates exactly the\n"
|
||||||
|
"same way, except it unpauses instead of pausing the given interface.\n"
|
||||||
|
"Example: UnpauseQueueMember(|SIP/3000)\n";
|
||||||
|
|
||||||
/* Persistent Members astdb family */
|
/* Persistent Members astdb family */
|
||||||
static const char *pm_family = "/Queue/PersistentMembers";
|
static const char *pm_family = "/Queue/PersistentMembers";
|
||||||
/* The maximum lengh of each persistent member queue database entry */
|
/* The maximum lengh of each persistent member queue database entry */
|
||||||
|
@ -214,6 +238,7 @@ struct member {
|
||||||
int calls; /* Number of calls serviced by this member */
|
int calls; /* Number of calls serviced by this member */
|
||||||
int dynamic; /* Are we dynamically added? */
|
int dynamic; /* Are we dynamically added? */
|
||||||
int status; /* Status of queue member */
|
int status; /* Status of queue member */
|
||||||
|
int paused; /* Are we paused (not accepting calls)? */
|
||||||
time_t lastcall; /* When last successful call was hungup */
|
time_t lastcall; /* When last successful call was hungup */
|
||||||
struct member *next; /* Next member */
|
struct member *next; /* Next member */
|
||||||
};
|
};
|
||||||
|
@ -367,9 +392,10 @@ static void *changethread(void *data)
|
||||||
"Penalty: %d\r\n"
|
"Penalty: %d\r\n"
|
||||||
"CallsTaken: %d\r\n"
|
"CallsTaken: %d\r\n"
|
||||||
"LastCall: %ld\r\n"
|
"LastCall: %ld\r\n"
|
||||||
"Status: %d\r\n",
|
"Status: %d\r\n"
|
||||||
|
"Paused: %d\r\n",
|
||||||
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
|
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
|
||||||
cur->penalty, cur->calls, cur->lastcall, cur->status);
|
cur->penalty, cur->calls, cur->lastcall, cur->status, cur->paused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
@ -693,9 +719,10 @@ static int update_status(struct ast_call_queue *q, struct member *member, int st
|
||||||
"Penalty: %d\r\n"
|
"Penalty: %d\r\n"
|
||||||
"CallsTaken: %d\r\n"
|
"CallsTaken: %d\r\n"
|
||||||
"LastCall: %ld\r\n"
|
"LastCall: %ld\r\n"
|
||||||
"Status: %d\r\n",
|
"Status: %d\r\n"
|
||||||
|
"Paused: %d\r\n",
|
||||||
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
|
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
|
||||||
cur->penalty, cur->calls, cur->lastcall, cur->status);
|
cur->penalty, cur->calls, cur->lastcall, cur->status, cur->paused);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
@ -789,6 +816,15 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tmp->member->paused) {
|
||||||
|
if (option_debug)
|
||||||
|
ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
|
||||||
|
if (qe->chan->cdr)
|
||||||
|
ast_cdr_busy(qe->chan->cdr);
|
||||||
|
tmp->stillgoing = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(tech, tmp->interface, sizeof(tech) - 1);
|
strncpy(tech, tmp->interface, sizeof(tech) - 1);
|
||||||
if ((location = strchr(tech, '/')))
|
if ((location = strchr(tech, '/')))
|
||||||
*location++ = '\0';
|
*location++ = '\0';
|
||||||
|
@ -1616,7 +1652,7 @@ static struct member * interface_exists(struct ast_call_queue *q, char *interfac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct member *create_queue_node(char *interface, int penalty)
|
static struct member *create_queue_node(char *interface, int penalty, int paused)
|
||||||
{
|
{
|
||||||
struct member *cur;
|
struct member *cur;
|
||||||
|
|
||||||
|
@ -1627,6 +1663,7 @@ static struct member *create_queue_node(char *interface, int penalty)
|
||||||
if (cur) {
|
if (cur) {
|
||||||
memset(cur, 0, sizeof(struct member));
|
memset(cur, 0, sizeof(struct member));
|
||||||
cur->penalty = penalty;
|
cur->penalty = penalty;
|
||||||
|
cur->paused = paused;
|
||||||
strncpy(cur->interface, interface, sizeof(cur->interface) - 1);
|
strncpy(cur->interface, interface, sizeof(cur->interface) - 1);
|
||||||
if (!strchr(cur->interface, '/'))
|
if (!strchr(cur->interface, '/'))
|
||||||
ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
|
ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
|
||||||
|
@ -1638,7 +1675,7 @@ static struct member *create_queue_node(char *interface, int penalty)
|
||||||
|
|
||||||
/* Dump all members in a specific queue to the databse
|
/* Dump all members in a specific queue to the databse
|
||||||
*
|
*
|
||||||
* <pm_family>/<queuename> = <interface>;<penalty>;...
|
* <pm_family>/<queuename> = <interface>;<penalty>;<paused>;...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void dump_queue_members(struct ast_call_queue *pm_queue)
|
static void dump_queue_members(struct ast_call_queue *pm_queue)
|
||||||
|
@ -1655,7 +1692,7 @@ static void dump_queue_members(struct ast_call_queue *pm_queue)
|
||||||
while (cur_member) {
|
while (cur_member) {
|
||||||
if (cur_member->dynamic) {
|
if (cur_member->dynamic) {
|
||||||
value_len = strlen(value);
|
value_len = strlen(value);
|
||||||
res = snprintf(value+value_len, sizeof(value)-value_len, "%s;%d;", cur_member->interface, cur_member->penalty);
|
res = snprintf(value+value_len, sizeof(value)-value_len, "%s;%d;%d;", cur_member->interface, cur_member->penalty, cur_member->paused);
|
||||||
if (res != strlen(value + value_len)) {
|
if (res != strlen(value + value_len)) {
|
||||||
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
|
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
|
||||||
break;
|
break;
|
||||||
|
@ -1721,7 +1758,7 @@ static int remove_from_queue(char *queuename, char *interface)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_to_queue(char *queuename, char *interface, int penalty)
|
static int add_to_queue(char *queuename, char *interface, int penalty, int paused)
|
||||||
{
|
{
|
||||||
struct ast_call_queue *q;
|
struct ast_call_queue *q;
|
||||||
struct member *new_member;
|
struct member *new_member;
|
||||||
|
@ -1732,7 +1769,7 @@ static int add_to_queue(char *queuename, char *interface, int penalty)
|
||||||
ast_mutex_lock(&q->lock);
|
ast_mutex_lock(&q->lock);
|
||||||
if (!strcmp(q->name, queuename)) {
|
if (!strcmp(q->name, queuename)) {
|
||||||
if (interface_exists(q, interface) == NULL) {
|
if (interface_exists(q, interface) == NULL) {
|
||||||
new_member = create_queue_node(interface, penalty);
|
new_member = create_queue_node(interface, penalty, paused);
|
||||||
|
|
||||||
if (new_member != NULL) {
|
if (new_member != NULL) {
|
||||||
new_member->dynamic = 1;
|
new_member->dynamic = 1;
|
||||||
|
@ -1745,9 +1782,10 @@ static int add_to_queue(char *queuename, char *interface, int penalty)
|
||||||
"Penalty: %d\r\n"
|
"Penalty: %d\r\n"
|
||||||
"CallsTaken: %d\r\n"
|
"CallsTaken: %d\r\n"
|
||||||
"LastCall: %ld\r\n"
|
"LastCall: %ld\r\n"
|
||||||
"Status: %d\r\n",
|
"Status: %d\r\n"
|
||||||
|
"Paused: %d\r\n",
|
||||||
q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
|
q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
|
||||||
new_member->penalty, new_member->calls, new_member->lastcall, new_member->status);
|
new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused);
|
||||||
|
|
||||||
if (queue_persistent_members)
|
if (queue_persistent_members)
|
||||||
dump_queue_members(q);
|
dump_queue_members(q);
|
||||||
|
@ -1768,6 +1806,49 @@ static int add_to_queue(char *queuename, char *interface, int penalty)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_member_paused(char *queuename, char *interface, int paused)
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
struct ast_call_queue *q;
|
||||||
|
struct member *mem;
|
||||||
|
|
||||||
|
/* Special event for when all queues are paused - individual events still generated */
|
||||||
|
|
||||||
|
if (ast_strlen_zero(queuename))
|
||||||
|
ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
|
||||||
|
|
||||||
|
ast_mutex_lock(&qlock);
|
||||||
|
for (q = queues ; q ; q = q->next) {
|
||||||
|
ast_mutex_lock(&q->lock);
|
||||||
|
if (ast_strlen_zero(queuename) || !strcmp(q->name, queuename)) {
|
||||||
|
if ((mem = interface_exists(q, interface))) {
|
||||||
|
found++;
|
||||||
|
if (mem->paused == paused)
|
||||||
|
ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
|
||||||
|
mem->paused = paused;
|
||||||
|
|
||||||
|
if (queue_persistent_members)
|
||||||
|
dump_queue_members(q);
|
||||||
|
|
||||||
|
ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
|
||||||
|
|
||||||
|
manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
|
||||||
|
"Queue: %s\r\n"
|
||||||
|
"Location: %s\r\n"
|
||||||
|
"Paused: %d\r\n",
|
||||||
|
q->name, mem->interface, paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast_mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
ast_mutex_unlock(&qlock);
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
else
|
||||||
|
return RESULT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add members saved in the queue members DB file saves
|
/* Add members saved in the queue members DB file saves
|
||||||
* created by dump_queue_members(), back into the queues */
|
* created by dump_queue_members(), back into the queues */
|
||||||
static void reload_queue_members(void)
|
static void reload_queue_members(void)
|
||||||
|
@ -1777,6 +1858,8 @@ static void reload_queue_members(void)
|
||||||
char *pm_interface;
|
char *pm_interface;
|
||||||
char *pm_penalty_tok;
|
char *pm_penalty_tok;
|
||||||
int pm_penalty = 0;
|
int pm_penalty = 0;
|
||||||
|
char *pm_paused_tok;
|
||||||
|
int pm_paused = 0;
|
||||||
struct ast_db_entry *pm_db_tree = NULL;
|
struct ast_db_entry *pm_db_tree = NULL;
|
||||||
int pm_family_len = 0;
|
int pm_family_len = 0;
|
||||||
struct ast_call_queue *cur_queue = NULL;
|
struct ast_call_queue *cur_queue = NULL;
|
||||||
|
@ -1813,12 +1896,13 @@ static void reload_queue_members(void)
|
||||||
ast_mutex_unlock(&cur_queue->lock);
|
ast_mutex_unlock(&cur_queue->lock);
|
||||||
|
|
||||||
if (!ast_db_get(pm_family, pm_queue_name, queue_data, PM_MAX_LEN)) {
|
if (!ast_db_get(pm_family, pm_queue_name, queue_data, PM_MAX_LEN)) {
|
||||||
/* Parse each <interface>;<penalty>; from the value of the
|
|
||||||
* queuename key and add it to the respective queue */
|
|
||||||
cur_pm_ptr = queue_data;
|
cur_pm_ptr = queue_data;
|
||||||
while ((pm_interface = strsep(&cur_pm_ptr, ";"))) {
|
while ((pm_interface = strsep(&cur_pm_ptr, ";"))) {
|
||||||
|
/* On the last iteration, pm_interface is a pointer to an empty string. Don't report a spurious error. */
|
||||||
|
if (pm_interface[0] == 0)
|
||||||
|
break;
|
||||||
if (!(pm_penalty_tok = strsep(&cur_pm_ptr, ";"))) {
|
if (!(pm_penalty_tok = strsep(&cur_pm_ptr, ";"))) {
|
||||||
ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s'\n", pm_queue_name);
|
ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (penalty)\n", pm_queue_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pm_penalty = strtol(pm_penalty_tok, NULL, 10);
|
pm_penalty = strtol(pm_penalty_tok, NULL, 10);
|
||||||
|
@ -1827,10 +1911,25 @@ static void reload_queue_members(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option_debug)
|
/* If ptr[1] is ';', the string is 1 char long and can't be an interface */
|
||||||
ast_log(LOG_DEBUG, "Reload Members: Queue: %s Member: %s Penalty: %d\n", pm_queue_name, pm_interface, pm_penalty);
|
|
||||||
|
|
||||||
if (add_to_queue(pm_queue_name, pm_interface, pm_penalty) == RES_OUTOFMEMORY) {
|
if (cur_pm_ptr[1] == ';') {
|
||||||
|
if (!(pm_paused_tok = strsep(&cur_pm_ptr, ";"))) {
|
||||||
|
ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (paused)\n", pm_queue_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pm_paused = strtol(pm_paused_tok, NULL, 10);
|
||||||
|
if ((errno == ERANGE) || (pm_paused < 0 || pm_paused > 1)) {
|
||||||
|
ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", pm_paused_tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (option_debug)
|
||||||
|
ast_verbose(VERBOSE_PREFIX_3 "Found old-format queue member %s:%s\n", pm_queue_name, pm_interface);
|
||||||
|
|
||||||
|
if (option_debug)
|
||||||
|
ast_log(LOG_DEBUG, "Reload Members: Queue: %s Member: %s Penalty: %d Paused: %d\n", pm_queue_name, pm_interface, pm_penalty, pm_paused);
|
||||||
|
|
||||||
|
if (add_to_queue(pm_queue_name, pm_interface, pm_penalty, pm_paused) == RES_OUTOFMEMORY) {
|
||||||
ast_log(LOG_ERROR, "Out of Memory when loading queue member from astdb\n");
|
ast_log(LOG_ERROR, "Out of Memory when loading queue member from astdb\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1848,6 +1947,90 @@ static void reload_queue_members(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pqm_exec(struct ast_channel *chan, void *data)
|
||||||
|
{
|
||||||
|
struct localuser *u;
|
||||||
|
char *queuename, *interface;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface])\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
queuename = ast_strdupa((char *)data);
|
||||||
|
if (!queuename) {
|
||||||
|
ast_log(LOG_ERROR, "Out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface = strchr(queuename, '|');
|
||||||
|
if (!interface) {
|
||||||
|
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL_USER_ADD(u);
|
||||||
|
|
||||||
|
*interface = '\0';
|
||||||
|
interface++;
|
||||||
|
|
||||||
|
if (set_member_paused(queuename, interface, 1)) {
|
||||||
|
ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", interface);
|
||||||
|
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
|
||||||
|
chan->priority += 100;
|
||||||
|
LOCAL_USER_REMOVE(u);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL_USER_REMOVE(u);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int upqm_exec(struct ast_channel *chan, void *data)
|
||||||
|
{
|
||||||
|
struct localuser *u;
|
||||||
|
char *queuename, *interface;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface])\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
queuename = ast_strdupa((char *)data);
|
||||||
|
if (!queuename) {
|
||||||
|
ast_log(LOG_ERROR, "Out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface = strchr(queuename, '|');
|
||||||
|
if (!interface) {
|
||||||
|
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL_USER_ADD(u);
|
||||||
|
|
||||||
|
*interface = '\0';
|
||||||
|
interface++;
|
||||||
|
|
||||||
|
if (set_member_paused(queuename, interface, 0)) {
|
||||||
|
ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", interface);
|
||||||
|
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
|
||||||
|
chan->priority += 100;
|
||||||
|
LOCAL_USER_REMOVE(u);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL_USER_REMOVE(u);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rqm_exec(struct ast_channel *chan, void *data)
|
static int rqm_exec(struct ast_channel *chan, void *data)
|
||||||
{
|
{
|
||||||
int res=-1;
|
int res=-1;
|
||||||
|
@ -1962,7 +2145,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (add_to_queue(queuename, interface, penalty)) {
|
switch (add_to_queue(queuename, interface, penalty, 0)) {
|
||||||
case RES_OKAY:
|
case RES_OKAY:
|
||||||
ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
|
ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -2502,6 +2685,8 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show)
|
||||||
max[0] = '\0';
|
max[0] = '\0';
|
||||||
if (mem->dynamic)
|
if (mem->dynamic)
|
||||||
strncat(max, " (dynamic)", sizeof(max) - strlen(max) - 1);
|
strncat(max, " (dynamic)", sizeof(max) - strlen(max) - 1);
|
||||||
|
if (mem->paused)
|
||||||
|
strncat(max, " (paused)", sizeof(max) - strlen(max) - 1);
|
||||||
if (mem->status)
|
if (mem->status)
|
||||||
snprintf(max + strlen(max), sizeof(max) - strlen(max), " (%s)", status2str(mem->status, tmpbuf, sizeof(tmpbuf)));
|
snprintf(max + strlen(max), sizeof(max) - strlen(max), " (%s)", status2str(mem->status, tmpbuf, sizeof(tmpbuf)));
|
||||||
if (mem->calls) {
|
if (mem->calls) {
|
||||||
|
@ -2615,10 +2800,11 @@ static int manager_queues_status( struct mansession *s, struct message *m )
|
||||||
"CallsTaken: %d\r\n"
|
"CallsTaken: %d\r\n"
|
||||||
"LastCall: %ld\r\n"
|
"LastCall: %ld\r\n"
|
||||||
"Status: %d\r\n"
|
"Status: %d\r\n"
|
||||||
|
"Paused: %d\r\n"
|
||||||
"%s"
|
"%s"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
|
q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
|
||||||
mem->penalty, mem->calls, mem->lastcall, mem->status, idText);
|
mem->penalty, mem->calls, mem->lastcall, mem->status, mem->paused, idText);
|
||||||
|
|
||||||
/* List Queue Entries */
|
/* List Queue Entries */
|
||||||
|
|
||||||
|
@ -2646,12 +2832,13 @@ static int manager_queues_status( struct mansession *s, struct message *m )
|
||||||
|
|
||||||
static int manager_add_queue_member(struct mansession *s, struct message *m)
|
static int manager_add_queue_member(struct mansession *s, struct message *m)
|
||||||
{
|
{
|
||||||
char *queuename, *interface, *penalty_s;
|
char *queuename, *interface, *penalty_s, *paused_s;
|
||||||
int penalty = 0;
|
int paused, penalty = 0;
|
||||||
|
|
||||||
queuename = astman_get_header(m, "Queue");
|
queuename = astman_get_header(m, "Queue");
|
||||||
interface = astman_get_header(m, "Interface");
|
interface = astman_get_header(m, "Interface");
|
||||||
penalty_s = astman_get_header(m, "Penalty");
|
penalty_s = astman_get_header(m, "Penalty");
|
||||||
|
paused_s = astman_get_header(m, "Paused");
|
||||||
|
|
||||||
if (ast_strlen_zero(queuename)) {
|
if (ast_strlen_zero(queuename)) {
|
||||||
astman_send_error(s, m, "'Queue' not specified.");
|
astman_send_error(s, m, "'Queue' not specified.");
|
||||||
|
@ -2669,7 +2856,12 @@ static int manager_add_queue_member(struct mansession *s, struct message *m)
|
||||||
penalty = 0;
|
penalty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (add_to_queue(queuename, interface, penalty)) {
|
if (ast_strlen_zero(paused_s))
|
||||||
|
paused = 0;
|
||||||
|
else
|
||||||
|
paused = abs(ast_true(paused_s));
|
||||||
|
|
||||||
|
switch (add_to_queue(queuename, interface, penalty, paused)) {
|
||||||
case RES_OKAY:
|
case RES_OKAY:
|
||||||
astman_send_ack(s, m, "Added interface to queue");
|
astman_send_ack(s, m, "Added interface to queue");
|
||||||
break;
|
break;
|
||||||
|
@ -2715,6 +2907,33 @@ static int manager_remove_queue_member(struct mansession *s, struct message *m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int manager_pause_queue_member(struct mansession *s, struct message *m)
|
||||||
|
{
|
||||||
|
char *queuename, *interface, *paused_s;
|
||||||
|
int paused;
|
||||||
|
|
||||||
|
interface = astman_get_header(m, "Interface");
|
||||||
|
paused_s = astman_get_header(m, "Paused");
|
||||||
|
queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */
|
||||||
|
|
||||||
|
if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
|
||||||
|
astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
paused = abs(ast_true(paused_s));
|
||||||
|
|
||||||
|
if (set_member_paused(queuename, interface, paused))
|
||||||
|
astman_send_error(s, m, "Interface not found");
|
||||||
|
else
|
||||||
|
if (paused)
|
||||||
|
astman_send_ack(s, m, "Interface paused successfully");
|
||||||
|
else
|
||||||
|
astman_send_ack(s, m, "Interface unpaused successfully");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_add_queue_member(int fd, int argc, char *argv[])
|
static int handle_add_queue_member(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *queuename, *interface;
|
char *queuename, *interface;
|
||||||
|
@ -2744,7 +2963,7 @@ static int handle_add_queue_member(int fd, int argc, char *argv[])
|
||||||
penalty = 0;
|
penalty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (add_to_queue(queuename, interface, penalty)) {
|
switch (add_to_queue(queuename, interface, penalty, 0)) {
|
||||||
case RES_OKAY:
|
case RES_OKAY:
|
||||||
ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
|
ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -2909,9 +3128,12 @@ int unload_module(void)
|
||||||
ast_manager_unregister("QueueStatus");
|
ast_manager_unregister("QueueStatus");
|
||||||
ast_manager_unregister("QueueAdd");
|
ast_manager_unregister("QueueAdd");
|
||||||
ast_manager_unregister("QueueRemove");
|
ast_manager_unregister("QueueRemove");
|
||||||
|
ast_manager_unregister("QueuePause");
|
||||||
ast_devstate_del(statechange_queue, NULL);
|
ast_devstate_del(statechange_queue, NULL);
|
||||||
ast_unregister_application(app_aqm);
|
ast_unregister_application(app_aqm);
|
||||||
ast_unregister_application(app_rqm);
|
ast_unregister_application(app_rqm);
|
||||||
|
ast_unregister_application(app_pqm);
|
||||||
|
ast_unregister_application(app_upqm);
|
||||||
return ast_unregister_application(app);
|
return ast_unregister_application(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2929,8 +3151,11 @@ int load_module(void)
|
||||||
ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" );
|
ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" );
|
||||||
ast_manager_register( "QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue." );
|
ast_manager_register( "QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue." );
|
||||||
ast_manager_register( "QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue." );
|
ast_manager_register( "QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue." );
|
||||||
|
ast_manager_register( "QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member, "Makes a queue member temporarily unavailable" );
|
||||||
ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip) ;
|
ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip) ;
|
||||||
ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip) ;
|
ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip) ;
|
||||||
|
ast_register_application(app_pqm, pqm_exec, app_pqm_synopsis, app_pqm_descrip) ;
|
||||||
|
ast_register_application(app_upqm, upqm_exec, app_upqm_synopsis, app_upqm_descrip) ;
|
||||||
}
|
}
|
||||||
reload_queues();
|
reload_queues();
|
||||||
|
|
||||||
|
|
Reference in a new issue