Skip to content
Snippets Groups Projects
app_queue.c 32.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    	char *cat, *tmp;
    	struct ast_variable *var;
    	struct member *prev, *cur;
    	int new;
    	cfg = ast_load("queues.conf");
    	if (!cfg) {
    		ast_log(LOG_NOTICE, "No call queueing config file, so no call queues\n");
    		return;
    	}
    	ast_pthread_mutex_lock(&qlock);
    	/* Mark all queues as dead for the moment */
    	q = queues;
    	while(q) {
    		q->dead = 1;
    		q = q->next;
    	}
    	/* Chug through config file */
    	cat = ast_category_browse(cfg, NULL);
    	while(cat) {
    		if (strcasecmp(cat, "general")) {
    			/* Look for an existing one */
    			q = queues;
    			while(q) {
    				if (!strcmp(q->name, cat))
    					break;
    				q = q->next;
    			}
    			if (!q) {
    				/* Make one then */
    				q = malloc(sizeof(struct ast_call_queue));
    				if (q) {
    					/* Initialize it */
    					memset(q, 0, sizeof(struct ast_call_queue));
    
    Mark Spencer's avatar
    Mark Spencer committed
    					ast_pthread_mutex_init(&q->lock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    					strncpy(q->name, cat, sizeof(q->name));
    					new = 1;
    				} else new = 0;
    			} else
    					new = 0;
    			if (q) {
    				if (!new) 
    					ast_pthread_mutex_lock(&q->lock);
    				/* Re-initialize the queue */
    				q->dead = 0;
    				q->retry = 0;
    				q->timeout = -1;
    				q->maxlen = 0;
    				free_members(q);
    				strcpy(q->moh, "");
    				strcpy(q->announce, "");
    				strcpy(q->context, "");
    				prev = NULL;
    				var = ast_variable_browse(cfg, cat);
    				while(var) {
    					if (!strcasecmp(var->name, "member")) {
    						/* Add a new member */
    						cur = malloc(sizeof(struct member));
    						if (cur) {
    							memset(cur, 0, sizeof(struct member));
    							strncpy(cur->tech, var->value, sizeof(cur->tech) - 1);
    							if ((tmp = strchr(cur->tech, '/')))
    								*tmp = '\0';
    							if ((tmp = strchr(var->value, '/'))) {
    								tmp++;
    								strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
    							} else
    								ast_log(LOG_WARNING, "No location at line %d of queue.conf\n", var->lineno);
    							if (prev)
    								prev->next = cur;
    							else
    								q->members = cur;
    							prev = cur;
    						}
    					} else if (!strcasecmp(var->name, "music")) {
    						strncpy(q->moh, var->value, sizeof(q->moh) - 1);
    					} else if (!strcasecmp(var->name, "announce")) {
    						strncpy(q->announce, var->value, sizeof(q->announce) - 1);
    					} else if (!strcasecmp(var->name, "context")) {
    						strncpy(q->context, var->value, sizeof(q->context) - 1);
    					} else if (!strcasecmp(var->name, "timeout")) {
    						q->timeout = atoi(var->value);
    					} else if (!strcasecmp(var->name, "retry")) {
    						q->retry = atoi(var->value);
    					} else if (!strcasecmp(var->name, "maxlen")) {
    						q->maxlen = atoi(var->value);
    					} else {
    						ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno);
    					}
    					var = var->next;
    				}
    				if (q->retry < 1)
    					q->retry = DEFAULT_RETRY;
    				if (q->timeout < 0)
    					q->timeout = DEFAULT_TIMEOUT;
    				if (q->maxlen < 0)
    					q->maxlen = 0;
    				if (!new) 
    					ast_pthread_mutex_unlock(&q->lock);
    				if (new) {
    					q->next = queues;
    					queues = q;
    				}
    			}
    		}
    		cat = ast_category_browse(cfg, cat);
    	}
    
    	ast_destroy(cfg);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	q = queues;
    	ql = NULL;
    	while(q) {
    		qn = q->next;
    		if (q->dead) {
    			if (ql)
    				ql->next = q->next;
    			else
    				queues = q->next;
    			if (!q->count) {
    				free(q);
    			} else
    				ast_log(LOG_WARNING, "XXX Leaking a litttle memory :( XXX\n");
    		} else
    			ql = q;
    		q = qn;
    	}
    	ast_pthread_mutex_unlock(&qlock);
    }
    
    static int queues_show(int fd, int argc, char **argv)
    {
    	struct ast_call_queue *q;
    	struct queue_ent *qe;
    	struct member *mem;
    	int pos;
    	time_t now;
    	char max[80];
    	
    	time(&now);
    	if (argc != 2)
    		return RESULT_SHOWUSAGE;
    	q = queues;
    	if (!q) {	
    		ast_cli(fd, "No queues.\n");
    		return RESULT_SUCCESS;
    	}
    	while(q) {
    		ast_pthread_mutex_lock(&q->lock);
    		if (q->maxlen)
    			snprintf(max, sizeof(max), "%d", q->maxlen);
    		else
    			strcpy(max, "unlimited");
    		ast_cli(fd, "%-12.12s has %d calls (max %s)\n", q->name, q->count, max);
    		if (q->members) {
    			ast_cli(fd, "   Members: \n");
    			for (mem = q->members; mem; mem = mem->next) 
    				ast_cli(fd, "      %s/%s\n", mem->tech, mem->loc);
    		} else
    			ast_cli(fd, "   No Members\n");
    		if (q->head) {
    			pos = 1;
    			ast_cli(fd, "   Callers: \n");
    			for (qe = q->head; qe; qe = qe->next) 
    				ast_cli(fd, "      %d. %s (wait: %d:%02.2d)\n", pos++, qe->chan->name,
    								(now - qe->start) / 60, (now - qe->start) % 60);
    		} else
    			ast_cli(fd, "   No Callers\n");
    		ast_cli(fd, "\n");
    		ast_pthread_mutex_unlock(&q->lock);
    		q = q->next;
    	}
    	return RESULT_SUCCESS;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    /* JDG: callback to display queues status in manager */
    static int manager_queues_show( struct mansession *s, struct message *m )
    {
    	char *a[] = { "show", "queues" };
    	return queues_show( s->fd, 2, a );
    } /* /JDG */
    
    
    
    /* Dump queue status */
    static int manager_queues_status( struct mansession *s, struct message *m )
    {
    	time_t now;
    	int pos;
    	struct ast_call_queue *q;
    	struct queue_ent *qe;
    	astman_send_ack(s, "Queue status will follow");
    	time(&now);
    	q = queues;
    	while(q) {
    		ast_pthread_mutex_lock(&q->lock);
    		ast_cli(s->fd, "Event: QueueParams\r\n"
    					"Queue: %s\r\n"
    					"Max: %d\r\n"
    					"Calls: %d\r\n"
    					"\r\n",
    						q->name, q->maxlen, q->count);
    #if 0
    		/* Do we care about queue members? */					
    		for (mem = q->members; mem; mem = mem->next) 
    			ast_cli(fd, "      %s/%s\n", mem->tech, mem->loc);
    #endif			
    		pos = 1;
    		for (qe = q->head; qe; qe = qe->next) 
    			ast_cli(s->fd, "Event: QueueMember\r\n"
    				"Queue: %s\r\n"
    				"Position: %d\r\n"
    				"Channel: %s\r\n"
    				"CallerID: %s\r\n"
    				"Wait: %ld\r\n"
    				"\r\n", 
    
    Mark Spencer's avatar
    Mark Spencer committed
    					q->name, pos++, qe->chan->name, (qe->chan->callerid ? qe->chan->callerid : ""), now - qe->start);
    
    		ast_pthread_mutex_unlock(&q->lock);
    		q = q->next;
    	}
    	return RESULT_SUCCESS;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    static char show_queues_usage[] = 
    "Usage: show queues\n"
    "       Provides summary information on call queues.\n";
    
    static struct ast_cli_entry cli_show_queues = {
    	{ "show", "queues", NULL }, queues_show, 
    	"Show status of queues", show_queues_usage, NULL };
    
    int unload_module(void)
    {
    	STANDARD_HANGUP_LOCALUSERS;
    	ast_cli_unregister(&cli_show_queues);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_manager_unregister( "Queues" );
    
    	ast_manager_unregister( "QueueStatus" );
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return ast_unregister_application(app);
    }
    
    int load_module(void)
    {
    	int res;
    	res = ast_register_application(app, queue_exec, synopsis, descrip);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (!res) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_cli_register(&cli_show_queues);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_manager_register( "Queues", 0, manager_queues_show, "Queues" );
    
    		ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" );
    
    
    		// [PHM 06/26/03]
    		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) ;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	reload_queues();
    	return res;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    int reload(void)
    {
    	reload_queues();
    	return 0;
    }
    
    char *description(void)
    {
    	return tdesc;
    }
    
    int usecount(void)
    {
    	int res;
    	STANDARD_USECOUNT(res);
    	return res;
    }
    
    char *key()
    {
    	return ASTERISK_GPL_KEY;
    }