Newer
Older
if (q->callscompleted > 0)
sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
astman_append(s, "Event: QueueParams\r\n"
"Queue: %s\r\n"
"Max: %d\r\n"
"Calls: %d\r\n"
"Holdtime: %d\r\n"
"Completed: %d\r\n"
"Abandoned: %d\r\n"
"ServiceLevel: %d\r\n"
"ServicelevelPerf: %2.1f\r\n"
"Weight: %d\r\n"
"%s"
"\r\n",
q->name, q->maxlen, q->count, q->holdtime, q->callscompleted,
q->callsabandoned, q->servicelevel, sl, q->weight, idText);
/* List Queue Members */
for (mem = q->members; mem; mem = mem->next) {
if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
astman_append(s, "Event: QueueMember\r\n"
"Queue: %s\r\n"
"Location: %s\r\n"
"Membership: %s\r\n"
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n"
"%s"
"\r\n",
q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
}
}
/* List Queue Entries */
pos = 1;
for (qe = q->head; qe; qe = qe->next) {
astman_append(s, "Event: QueueEntry\r\n"
"Queue: %s\r\n"
"Position: %d\r\n"
"Channel: %s\r\n"
"CallerID: %s\r\n"
"CallerIDName: %s\r\n"
"Wait: %ld\r\n"
"%s"
"\r\n",
q->name, pos++, qe->chan->name,
S_OR(qe->chan->cid.cid_num, "unknown"),
S_OR(qe->chan->cid.cid_name, "unknown"),
(long) (now - qe->start), idText);
}
}
ast_mutex_unlock(&q->lock);
astman_append(s,
"Event: QueueStatusComplete\r\n"
"%s"
"\r\n",idText);
BJ Weschke
committed
AST_LIST_UNLOCK(&queues);
static int manager_add_queue_member(struct mansession *s, struct message *m)
{
char *queuename, *interface, *penalty_s, *paused_s;
int paused, penalty = 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");
if (ast_strlen_zero(queuename)) {
astman_send_error(s, m, "'Queue' not specified.");
return 0;
}
if (ast_strlen_zero(interface)) {
astman_send_error(s, m, "'Interface' not specified.");
return 0;
}
if (ast_strlen_zero(penalty_s))
penalty = 0;
else if (sscanf(penalty_s, "%d", &penalty) != 1)
penalty = 0;
if (ast_strlen_zero(paused_s))
paused = 0;
else
paused = abs(ast_true(paused_s));
switch (add_to_queue(queuename, interface, penalty, paused, queue_persistent_members)) {
case RES_OKAY:
astman_send_ack(s, m, "Added interface to queue");
break;
case RES_EXISTS:
astman_send_error(s, m, "Unable to add interface: Already there");
break;
case RES_NOSUCHQUEUE:
astman_send_error(s, m, "Unable to add interface to queue: No such queue");
break;
case RES_OUTOFMEMORY:
astman_send_error(s, m, "Out of memory");
break;
}
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
return 0;
}
static int manager_remove_queue_member(struct mansession *s, struct message *m)
{
char *queuename, *interface;
queuename = astman_get_header(m, "Queue");
interface = astman_get_header(m, "Interface");
if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
return 0;
}
switch (remove_from_queue(queuename, interface)) {
case RES_OKAY:
astman_send_ack(s, m, "Removed interface from queue");
break;
case RES_EXISTS:
astman_send_error(s, m, "Unable to remove interface: Not there");
break;
case RES_NOSUCHQUEUE:
astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
break;
case RES_OUTOFMEMORY:
astman_send_error(s, m, "Out of memory");
break;
}
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
astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
static int handle_add_queue_member(int fd, int argc, char *argv[])
{
char *queuename, *interface;
int penalty;
if ((argc != 6) && (argc != 8)) {
return RESULT_SHOWUSAGE;
} else if (strcmp(argv[4], "to")) {
return RESULT_SHOWUSAGE;
} else if ((argc == 8) && strcmp(argv[6], "penalty")) {
return RESULT_SHOWUSAGE;
}
queuename = argv[5];
interface = argv[3];
if (argc == 8) {
if (sscanf(argv[7], "%d", &penalty) == 1) {
if (penalty < 0) {
ast_cli(fd, "Penalty must be >= 0\n");
penalty = 0;
}
} else {
ast_cli(fd, "Penalty must be an integer >= 0\n");
penalty = 0;
}
} else {
penalty = 0;
}
switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
case RES_OKAY:
ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
return RESULT_SUCCESS;
case RES_EXISTS:
ast_cli(fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
return RESULT_FAILURE;
case RES_NOSUCHQUEUE:
ast_cli(fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
return RESULT_FAILURE;
case RES_OUTOFMEMORY:
ast_cli(fd, "Out of memory\n");
return RESULT_FAILURE;
default:
return RESULT_FAILURE;
}
}
Russell Bryant
committed
static char *complete_add_queue_member(const char *line, const char *word, int pos, int state)
{
/* 0 - add; 1 - queue; 2 - member; 3 - <member>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty> */
switch (pos) {
case 3: /* Don't attempt to complete name of member (infinite possibilities) */
return NULL;
case 4: /* only one possible match, "to" */
return state == 0 ? ast_strdup("to") : NULL;
case 5: /* <queue> */
return complete_queue(line, word, pos, state);
case 6: /* only one possible match, "penalty" */
return state == 0 ? ast_strdup("penalty") : NULL;
case 7:
if (state < 100) { /* 0-99 */
BJ Weschke
committed
char *num;
if ((num = ast_malloc(3))) {
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
sprintf(num, "%d", state);
}
return num;
} else {
return NULL;
}
default:
return NULL;
}
}
static int handle_remove_queue_member(int fd, int argc, char *argv[])
{
char *queuename, *interface;
if (argc != 6) {
return RESULT_SHOWUSAGE;
} else if (strcmp(argv[4], "from")) {
return RESULT_SHOWUSAGE;
}
queuename = argv[5];
interface = argv[3];
switch (remove_from_queue(queuename, interface)) {
case RES_OKAY:
ast_cli(fd, "Removed interface '%s' from queue '%s'\n", interface, queuename);
return RESULT_SUCCESS;
case RES_EXISTS:
ast_cli(fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
return RESULT_FAILURE;
case RES_NOSUCHQUEUE:
ast_cli(fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
return RESULT_FAILURE;
case RES_OUTOFMEMORY:
ast_cli(fd, "Out of memory\n");
return RESULT_FAILURE;
default:
return RESULT_FAILURE;
}
}
Russell Bryant
committed
static char *complete_remove_queue_member(const char *line, const char *word, int pos, int state)
{
int which = 0;
struct member *m;
/* 0 - add; 1 - queue; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
if (pos > 5 || pos < 3)
return NULL;
if (pos == 4) /* only one possible match, 'from' */
return state == 0 ? ast_strdup("from") : NULL;
if (pos == 5) /* No need to duplicate code */
return complete_queue(line, word, pos, state);
/* here is the case for 3, <member> */
if (!AST_LIST_EMPTY(&queues)) { /* XXX unnecessary ? the traverse does that for us */
ast_mutex_lock(&q->lock);
for (m = q->members ; m ; m = m->next) {
if (++which > state) {
ast_mutex_unlock(&q->lock);
}
}
ast_mutex_unlock(&q->lock);
}
}
return NULL;
}
"Usage: show queues\n"
" Provides summary information on call queues.\n";
static struct ast_cli_entry cli_show_queues = {
"Show status of queues", show_queues_usage, NULL };
"Usage: show queue\n"
" Provides summary information on a specified queue.\n";
static struct ast_cli_entry cli_show_queue = {
"Show status of a specified queue", show_queue_usage, complete_queue };
static char aqm_cmd_usage[] =
"Usage: add queue member <channel> to <queue> [penalty <penalty>]\n";
static struct ast_cli_entry cli_add_queue_member = {
{ "add", "queue", "member", NULL }, handle_add_queue_member,
"Add a channel to a specified queue", aqm_cmd_usage, complete_add_queue_member };
static char rqm_cmd_usage[] =
"Usage: remove queue member <channel> from <queue>\n";
static struct ast_cli_entry cli_remove_queue_member = {
{ "remove", "queue", "member", NULL }, handle_remove_queue_member,
"Removes a channel from a specified queue", rqm_cmd_usage, complete_remove_queue_member };
static int unload_module(void)
Russell Bryant
committed
int res;
res = ast_cli_unregister(&cli_show_queue);
res |= ast_cli_unregister(&cli_show_queues);
res |= ast_cli_unregister(&cli_add_queue_member);
res |= ast_cli_unregister(&cli_remove_queue_member);
res |= ast_manager_unregister("Queues");
res |= ast_manager_unregister("QueueStatus");
res |= ast_manager_unregister("QueueAdd");
res |= ast_manager_unregister("QueueRemove");
res |= ast_manager_unregister("QueuePause");
res |= ast_unregister_application(app_aqm);
res |= ast_unregister_application(app_rqm);
res |= ast_unregister_application(app_pqm);
res |= ast_unregister_application(app_upqm);
res |= ast_unregister_application(app_ql);
Russell Bryant
committed
res |= ast_custom_function_unregister(&queueagentcount_function);
res |= ast_custom_function_unregister(&queuemembercount_function);
res |= ast_custom_function_unregister(&queuememberlist_function);
res |= ast_custom_function_unregister(&queuewaitingcount_function);
Russell Bryant
committed
res |= ast_unregister_application(app);
ast_module_user_hangup_all();
clear_and_free_interfaces();
Russell Bryant
committed
return res;
static int load_module(void)
if(!reload_queues())
return AST_MODULE_LOAD_DECLINE;
if (queue_persistent_members)
reload_queue_members();
res = ast_register_application(app, queue_exec, synopsis, descrip);
Russell Bryant
committed
res |= ast_cli_register(&cli_show_queue);
res |= ast_cli_register(&cli_show_queues);
res |= ast_cli_register(&cli_add_queue_member);
res |= ast_cli_register(&cli_remove_queue_member);
res |= ast_manager_register("Queues", 0, manager_queues_show, "Queues");
res |= ast_manager_register("QueueStatus", 0, manager_queues_status, "Queue Status");
res |= ast_manager_register("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue.");
res |= ast_manager_register("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue.");
res |= ast_manager_register("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member, "Makes a queue member temporarily unavailable");
res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip);
res |= ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip);
res |= ast_register_application(app_pqm, pqm_exec, app_pqm_synopsis, app_pqm_descrip);
res |= ast_register_application(app_upqm, upqm_exec, app_upqm_synopsis, app_upqm_descrip);
res |= ast_register_application(app_ql, ql_exec, app_ql_synopsis, app_ql_descrip);
Russell Bryant
committed
res |= ast_custom_function_register(&queueagentcount_function);
res |= ast_custom_function_register(&queuemembercount_function);
res |= ast_custom_function_register(&queuememberlist_function);
res |= ast_custom_function_register(&queuewaitingcount_function);
BJ Weschke
committed
res |= ast_devstate_add(statechange_queue, NULL);
Russell Bryant
committed
static int reload(void)
{
reload_queues();
return 0;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "True Call Queueing",
.load = load_module,
.unload = unload_module,
.reload = reload,
);