Skip to content
Snippets Groups Projects
app_queue.c 170 KiB
Newer Older
  • Learn to ignore specific revisions
  • Tilghman Lesher's avatar
    Tilghman Lesher committed
    				"Queue: %s\r\n"
    				"Max: %d\r\n"
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    				"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, int2strat(q->strategy), q->count, q->holdtime, q->callscompleted,
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    				q->callsabandoned, q->servicelevel, sl, q->weight, idText);
    
    			mem_iter = ao2_iterator_init(q->members, 0);
    			while ((mem = ao2_iterator_next(&mem_iter))) {
    
    				if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
    
    					astman_append(s, "Event: QueueMember\r\n"
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    						"Queue: %s\r\n"
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    						"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->membername, mem->interface, mem->dynamic ? "dynamic" : "static",
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    						mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
    
    				ao2_ref(mem, -1);
    
    			}
    			/* List Queue Entries */
    			pos = 1;
    			for (qe = q->head; qe; qe = qe->next) {
    
    				astman_append(s, "Event: QueueEntry\r\n"
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    					"Queue: %s\r\n"
    					"Position: %d\r\n"
    					"Channel: %s\r\n"
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    					"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);
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    		"Event: QueueStatusComplete\r\n"
    		"%s"
    		"\r\n",idText);
    
    	return RESULT_SUCCESS;
    }
    
    
    static int manager_add_queue_member(struct mansession *s, const struct message *m)
    
    	const char *queuename, *interface, *penalty_s, *paused_s, *membername;
    
    	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");
    
    	membername = astman_get_header(m, "MemberName");
    
    
    	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, membername, penalty, paused, queue_persistent_members)) {
    
    		ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
    
    		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;
    	}
    
    static int manager_remove_queue_member(struct mansession *s, const struct message *m)
    
    	const 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:
    
    		ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
    
    		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;
    
    	case RES_NOT_DYNAMIC:
    		astman_send_error(s, m, "Member not dynamic");
    		break;
    
    static int manager_pause_queue_member(struct mansession *s, const struct message *m)
    
    	const char *queuename, *interface, *paused_s, *reason;
    
    	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 */
    	reason = astman_get_header(m, "Reason");        /* Optional - Only used for logging purposes */
    
    
    	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, reason, paused))
    
    		astman_send_error(s, m, "Interface not found");
    	else
    
    		astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
    
    static int manager_queue_log_custom(struct mansession *s, const struct message *m)
    
    	const char *queuename, *event, *message, *interface, *uniqueid;
    
    
    	queuename = astman_get_header(m, "Queue");
    	uniqueid = astman_get_header(m, "UniqueId");
    	interface = astman_get_header(m, "Interface");
    	event = astman_get_header(m, "Event");
    	message = astman_get_header(m, "Message");
    
    	if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
    		astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
    		return 0;
    	}
    
    	ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
    	astman_send_ack(s, m, "Event added successfully");
    
    	return 0;
    }
    
    
    static char *complete_queue_add_member(const char *line, const char *word, int pos, int state)
    
    	/* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
    
    	case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
    
    	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;
    
    		if (state < 100) {      /* 0-99 */
    
    				sprintf(num, "%d", state);
    			}
    			return num;
    		} else {
    			return NULL;
    		}
    
    	case 8: /* only one possible match, "as" */
    		return state == 0 ? ast_strdup("as") : NULL;
    
    	case 9: /* Don't attempt to complete name of member (infinite possibilities) */
    
    		return NULL;
    
    static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
    {
    	const char *queuename, *interface, *penalty_s;
    	int penalty;
    
    	interface = astman_get_header(m, "Interface");
    	penalty_s = astman_get_header(m, "Penalty");
    	/* Optional - if not supplied, set the penalty value for the given Interface in all queues */
    	queuename = astman_get_header(m, "Queue");
    
    	if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
    		astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
    		return 0;
    	}
     
    	penalty = atoi(penalty_s);
    
    	if (set_member_penalty((char *)queuename, (char *)interface, penalty))
    		astman_send_error(s, m, "Invalid interface or queuename");
    	else
    		astman_send_ack(s, m, "Interface penalty set successfully");
    
    	return 0;
    }
    
    
    static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    
    	char *queuename, *interface, *membername = NULL;
    	int penalty;
    
    	switch ( cmd ) {
    	case CLI_INIT:
    		e->command = "queue add member";
    		e->usage =
    			"Usage: queue add member <channel> to <queue> [penalty <penalty>]\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)) {
    		return CLI_SHOWUSAGE;
    	} else if (strcmp(a->argv[4], "to")) {
    		return CLI_SHOWUSAGE;
    	} else if ((a->argc == 8) && strcmp(a->argv[6], "penalty")) {
    		return CLI_SHOWUSAGE;
    	} else if ((a->argc == 10) && strcmp(a->argv[8], "as")) {
    		return CLI_SHOWUSAGE;
    	}
    
    	queuename = a->argv[5];
    	interface = a->argv[3];
    	if (a->argc >= 8) {
    		if (sscanf(a->argv[7], "%d", &penalty) == 1) {
    			if (penalty < 0) {
    				ast_cli(a->fd, "Penalty must be >= 0\n");
    				penalty = 0;
    			}
    		} else {
    			ast_cli(a->fd, "Penalty must be an integer >= 0\n");
    			penalty = 0;
    		}
    	} else {
    		penalty = 0;
    	}
    
    	if (a->argc >= 10) {
    		membername = a->argv[9];
    	}
    
    	switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members)) {
    
    		ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
    		ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
    		return CLI_SUCCESS;
    
    		ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
    		return CLI_FAILURE;
    
    		ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
    		return CLI_FAILURE;
    
    		ast_cli(a->fd, "Out of memory\n");
    		return CLI_FAILURE;
    
    	case RES_NOT_DYNAMIC:
    
    Mark Michelson's avatar
    Mark Michelson committed
    		ast_cli(a->fd, "Member not dynamic\n");
    		return CLI_FAILURE;
    
    		return CLI_FAILURE;
    
    static char *complete_queue_remove_member(const char *line, const char *word, int pos, int state)
    
    	struct call_queue *q;
    
    	struct ao2_iterator mem_iter;
    
    	int wordlen = strlen(word);
    
    	/* 0 - queue; 1 - remove; 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> */
    
    	queue_iter = ao2_iterator_init(queues, 0);
    	while ((q = ao2_iterator_next(&queue_iter))) {
    		ao2_lock(q);
    		mem_iter = ao2_iterator_init(q->members, 0);
    		while ((m = ao2_iterator_next(&mem_iter))) {
    			if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
    				char *tmp;
    				ao2_unlock(q);
    				tmp = m->membername;
    
    				return ast_strdup(tmp);
    
    static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	char *queuename, *interface;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "queue remove member";
    		e->usage = "Usage: queue remove member <channel> from <queue>\n"; 
    		return NULL;
    	case CLI_GENERATE:
    		return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
    	}
    
    	if (a->argc != 6) {
    		return CLI_SHOWUSAGE;
    	} else if (strcmp(a->argv[4], "from")) {
    		return CLI_SHOWUSAGE;
    	}
    
    	queuename = a->argv[5];
    	interface = a->argv[3];
    
    	switch (remove_from_queue(queuename, interface)) {
    	case RES_OKAY:
    		ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
    		ast_cli(a->fd, "Removed interface '%s' from queue '%s'\n", interface, queuename);
    		return CLI_SUCCESS;
    	case RES_EXISTS:
    		ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
    		return CLI_FAILURE;
    	case RES_NOSUCHQUEUE:
    		ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
    		return CLI_FAILURE;
    	case RES_OUTOFMEMORY:
    		ast_cli(a->fd, "Out of memory\n");
    		return CLI_FAILURE;
    	default:
    		return CLI_FAILURE;
    	}
    }
    
    
    static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
    {
    
    	/* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
    
    	switch (pos) {
    	case 3:	/* Don't attempt to complete name of interface (infinite possibilities) */
    		return NULL;
    
    	case 4:	/* only one possible match, "queue" */
    		return state == 0 ? ast_strdup("queue") : NULL;
    
    	case 5:	/* <queue> */
    		return complete_queue(line, word, pos, state);
    	case 6: /* "reason" */
    		return state == 0 ? ast_strdup("reason") : NULL;
    	case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
    		return NULL;
    	default:
    		return NULL;
    	}
    }
    
    static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	char *queuename, *interface, *reason;
    	int paused;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "queue {pause|unpause} member";
    		e->usage = 
    
    			"Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
    
    			"		Pause or unpause a queue member. Not specifying a particular queue\n"
    			"		will pause or unpause a member across all queues to which the member\n"
    			"		belongs.\n";
    		return NULL;
    	case CLI_GENERATE:
    		return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
    	}
    
    	if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
    		return CLI_SHOWUSAGE;
    
    	} else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
    		return CLI_SHOWUSAGE;
    	} else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
    
    		return CLI_SHOWUSAGE;
    	}
    
    
    	interface = a->argv[3];
    	queuename = a->argc >= 6 ? a->argv[5] : NULL;
    	reason = a->argc == 8 ? a->argv[7] : NULL;
    	paused = !strcasecmp(a->argv[1], "pause");
    
    	if(set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
    		ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
    		if(!ast_strlen_zero(queuename))
    			ast_cli(a->fd, " in queue '%s'", queuename);
    		if(!ast_strlen_zero(reason))
    			ast_cli(a->fd, " for reason '%s'", reason);
    		ast_cli(a->fd, "\n");
    		return CLI_SUCCESS;
    	} else {
    		ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
    		if(!ast_strlen_zero(queuename))
    			ast_cli(a->fd, " in queue '%s'", queuename);
    		if(!ast_strlen_zero(reason))
    			ast_cli(a->fd, " for reason '%s'", reason);
    		ast_cli(a->fd, "\n");
    		return CLI_FAILURE;
    	}
    }
    
    
    static char *complete_queue_set_member_penalty(const char *line, const char *word, int pos, int state)
    {
    	/* 0 - queue; 1 - set; 2 - penalty; 3 - <penalty>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
    	switch (pos) {
    	case 4:
    		if (state == 0) {
    			return ast_strdup("on");
    		} else {
    			return NULL;
    		}
    	case 6:
    		if (state == 0) {
    			return ast_strdup("in");
    		} else {
    			return NULL;
    		}
    	case 7:
    		return complete_queue(line, word, pos, state);
    	default:
    		return NULL;
    	}
    }
     
    static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	char *queuename = NULL, *interface;
    	int penalty = 0;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "queue set penalty";
    		e->usage = 
    		"Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
    		"Set a member's penalty in the queue specified. If no queue is specified\n"
    		"then that interface's penalty is set in all queues to which that interface is a member\n";
    		return NULL;
    	case CLI_GENERATE:
    		return complete_queue_set_member_penalty(a->line, a->word, a->pos, a->n);
    	}
    
    	if (a->argc != 6 && a->argc != 8) {
    		return CLI_SHOWUSAGE;
    	} else if (strcmp(a->argv[5], "from")) {
    		return CLI_SHOWUSAGE;
    	}
    
    	if(a->argc == 8)
    		queuename = a->argv[7];
    	interface = a->argv[5];
    	penalty = atoi(a->argv[3]);
    
    	if (penalty < 0) {
    		ast_cli(a->fd, "Invalid penalty (%d)\n", penalty);
    		return CLI_FAILURE;
    	}
    
    	switch (set_member_penalty(queuename, interface, penalty)) {
    	case RESULT_SUCCESS:
    		ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
    		return CLI_SUCCESS;
    	case RESULT_FAILURE:
    		ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
    		return CLI_FAILURE;
    	default:
    		return CLI_FAILURE;
    	}
    }
    
    
    static const char qpm_cmd_usage[] = 
    "Usage: queue pause member <channel> in <queue> reason <reason>\n";
    
    static const char qum_cmd_usage[] =
    "Usage: queue unpause member <channel> in <queue> reason <reason>\n";
    
    
    static const char qsmp_cmd_usage[] =
    "Usage: queue set member penalty <channel> from <queue> <penalty>\n";
    
    
    static struct ast_cli_entry cli_queue[] = {
    
    	AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
    	AST_CLI_DEFINE(handle_queue_add_member, "Add a channel to a specified queue"),
    	AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
    	AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
    
    	AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
    
    static int unload_module(void)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	if (device_state.thread != AST_PTHREADT_NULL) {
    		device_state.stop = 1;
    		ast_mutex_lock(&device_state.lock);
    		ast_cond_signal(&device_state.cond);
    		ast_mutex_unlock(&device_state.lock);
    		pthread_join(device_state.thread, NULL);
    	}
    
    
    	ast_cli_unregister_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
    	res = ast_manager_unregister("QueueStatus");
    
    	res |= ast_manager_unregister("Queues");
    	res |= ast_manager_unregister("QueueStatus");
    
    	res |= ast_manager_unregister("QueueSummary");
    
    	res |= ast_manager_unregister("QueueAdd");
    	res |= ast_manager_unregister("QueueRemove");
    	res |= ast_manager_unregister("QueuePause");
    
    	res |= ast_manager_unregister("QueueLog");
    
    	res |= ast_manager_unregister("QueuePenalty");
    
    	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);
    
    	res |= ast_unregister_application(app);
    
    	res |= ast_custom_function_unregister(&queuevar_function);
    
    	res |= ast_custom_function_unregister(&queuemembercount_function);
    
    	res |= ast_custom_function_unregister(&queuemembercount_dep);
    
    	res |= ast_custom_function_unregister(&queuememberlist_function);
    
    	res |= ast_custom_function_unregister(&queuewaitingcount_function);
    
    	res |= ast_custom_function_unregister(&queuememberpenalty_function);
    
    
    	if (device_state_sub)
    		ast_event_unsubscribe(device_state_sub);
    
    	if ((con = ast_context_find("app_queue_gosub_virtual_context"))) {
    		ast_context_remove_extension2(con, "s", 1, NULL);
    
    		ast_context_destroy(con, "app_queue"); /* leave no trace */
    
    	clear_and_free_interfaces();
    
    static int load_module(void)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	int res;
    
    	queues = ao2_container_alloc(MAX_QUEUE_BUCKETS, queue_hash_cb, queue_cmp_cb);
    
    
    		return AST_MODULE_LOAD_DECLINE;
    
    	con = ast_context_find("app_queue_gosub_virtual_context");
    
    		con = ast_context_create(NULL, "app_queue_gosub_virtual_context", "app_queue");
    
    	if (!con)
    		ast_log(LOG_ERROR, "Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
    	else
    
    		ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_queue");
    
    	if (queue_persistent_members)
    		reload_queue_members();
    
    
    	ast_mutex_init(&device_state.lock);
    	ast_cond_init(&device_state.cond, NULL);
    	ast_pthread_create(&device_state.thread, NULL, device_state_thread, NULL);
    
    
    	ast_cli_register_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	res = ast_register_application(app, queue_exec, synopsis, descrip);
    
    	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);
    
    	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("QueueSummary", 0, manager_queues_summary, "Queue Summary");
    
    	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_manager_register("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom, "Adds custom entry in queue_log");
    
    	res |= ast_manager_register("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty, "Set the penalty for a queue member"); 
    
    	res |= ast_custom_function_register(&queuevar_function);
    
    	res |= ast_custom_function_register(&queuemembercount_function);
    
    	res |= ast_custom_function_register(&queuemembercount_dep);
    
    	res |= ast_custom_function_register(&queuememberlist_function);
    
    	res |= ast_custom_function_register(&queuewaitingcount_function);
    
    	res |= ast_custom_function_register(&queuememberpenalty_function);
    
    	if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, AST_EVENT_IE_END)))
    		res = -1;
    
    	return res ? AST_MODULE_LOAD_DECLINE : 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return 0;
    }
    
    
    AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "True Call Queueing",
    		.load = load_module,
    		.unload = unload_module,
    		.reload = reload,
    	       );