Index: asterisk/apps/app_queue.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v retrieving revision 1.4 diff -u -r1.4 app_queue.c --- asterisk/apps/app_queue.c 19 May 2003 01:07:06 -0000 1.4 +++ asterisk/apps/app_queue.c 26 Jun 2003 16:35:18 -0000 @@ -35,6 +35,8 @@ #include #include +#include + #include #define DEFAULT_RETRY 5 @@ -63,6 +65,28 @@ " The optionnal URL will be sent to the called party if the channel supports\n" "it.\n"; +// [PHM 06/26/03] +static char *app_aqm = "AddQueueMember" ; +static char *app_aqm_synopsis = "Dynamically adds queue members" ; +static char *app_aqm_descrip = +" AddQueueMember(queuename[|interface]):\n" +"Dynamically adds interface to an existing queue\n" +"Returns -1 if there is an error.\n" +"Example: AddQueueMember(techsupport|SIP/3000)\n" +""; + +static char *app_rqm = "RemoveQueueMember" ; +static char *app_rqm_synopsis = "Dynamically removes queue members" ; +static char *app_rqm_descrip = +" RemoveQueueMember(queuename[|interface]):\n" +"Dynamically removes interface to an existing queue\n" +"Returns -1 if there is an error.\n" +"Example: RemoveQueueMember(techsupport|SIP/3000)\n" +""; + + + + /* We define a customer "local user" structure because we use it not only for keeping track of what is in use but also for keeping track of who we're dialing. */ @@ -158,7 +182,9 @@ manager_event(EVENT_FLAG_CALL, "Join", "Channel: %s\r\nQueue: %s\r\nPosition: %d\r\n", qe->chan->name, q->name, qe->pos ); - +#if 1 +ast_log(LOG_NOTICE, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos ); +#endif } ast_pthread_mutex_unlock(&q->lock); break; @@ -211,15 +237,20 @@ if (!q) return; ast_pthread_mutex_lock(&q->lock); - /* Take us out of the queue */ - manager_event(EVENT_FLAG_CALL, "Leave", - "Channel: %s\r\nQueue: %s\r\n", - qe->chan->name, q->name ); + prev = NULL; cur = q->head; while(cur) { if (cur == qe) { q->count--; + + /* Take us out of the queue */ + manager_event(EVENT_FLAG_CALL, "Leave", + "Channel: %s\r\nQueue: %s\r\n", + qe->chan->name, q->name ); +#if 1 +ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name ); +#endif /* Take us out of the queue */ if (prev) prev->next = cur->next; @@ -636,6 +667,217 @@ return 0; } +// [PHM 06/26/03] + +static struct member * interface_exists( struct ast_call_queue * q, char * interface ) +{ + struct member * ret = NULL ; + struct member *mem; + char buf[500] ; + + if( q != NULL ) + { + mem = q->members ; + + while( mem != NULL ) { + sprintf( buf, "%s/%s", mem->tech, mem->loc); + + if( strcmp( buf, interface ) == 0 ) { + ret = mem ; + break ; + } + else + mem = mem->next ; + } + } + + return( ret ) ; +} + + +static struct member * create_queue_node( char * interface ) +{ + struct member * cur ; + char * tmp ; + + /* Add a new member */ + + cur = malloc(sizeof(struct member)); + + if (cur) { + memset(cur, 0, sizeof(struct member)); + strncpy(cur->tech, interface, sizeof(cur->tech) - 1); + if ((tmp = strchr(cur->tech, '/'))) + *tmp = '\0'; + if ((tmp = strchr(interface, '/'))) { + tmp++; + strncpy(cur->loc, tmp, sizeof(cur->loc) - 1); + } else + ast_log(LOG_WARNING, "No location at interface '%s'\n", interface); + } + + return( cur ) ; +} + + +static int rqm_exec(struct ast_channel *chan, void *data) +{ + int res=-1; + struct localuser *u; + char *queuename; + struct member * node ; + struct member * look ; + char info[512]; + char *interface=NULL; + struct ast_call_queue *q; + int found=0 ; + + if (!data) { + ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename|optional interface)\n"); + return -1; + } + + LOCAL_USER_ADD(u); // not sure if we need this, but better be safe than sorry ;-) + + /* Parse our arguments XXX Check for failure XXX */ + strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1); + queuename = info; + if (queuename) { + interface = strchr(queuename, '|'); + if (interface) { + *interface = '\0'; + interface++; + } + else + interface = chan->name ; + } + + if( ( q = queues) != NULL ) + { + while( q && ( res != 0 ) && (!found) ) + { + ast_pthread_mutex_lock(&q->lock); + if( strcmp( q->name, queuename) == 0 ) + { + // found queue, try to remove interface + found=1 ; + + if( ( node = interface_exists( q, interface ) ) != NULL ) + { + if( ( look = q->members ) == node ) + { + // 1st + q->members = node->next; + } + else + { + while( look != NULL ) + if( look->next == node ) + { + look->next = node->next ; + break ; + } + else + look = look->next ; + } + + free( node ) ; + + ast_log(LOG_NOTICE, "Removed interface '%s' to queue '%s'\n", + interface, queuename); + res = 0 ; + } + else + ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': " + "Not there\n", interface, queuename); + } + + ast_pthread_mutex_unlock(&q->lock); + q = q->next; + } + } + + if( ! found ) + ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", queuename); + + LOCAL_USER_REMOVE(u); + return res; +} + + + +static int aqm_exec(struct ast_channel *chan, void *data) +{ + int res=-1; + struct localuser *u; + char *queuename; + char info[512]; + char *interface=NULL; + struct ast_call_queue *q; + struct member *save; + int found=0 ; + + if (!data) { + ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename|optional interface)\n"); + return -1; + } + + LOCAL_USER_ADD(u); // not sure if we need this, but better be safe than sorry ;-) + + /* Parse our arguments XXX Check for failure XXX */ + strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1); + queuename = info; + if (queuename) { + interface = strchr(queuename, '|'); + if (interface) { + *interface = '\0'; + interface++; + } + else + interface = chan->name ; + } + + if( ( q = queues) != NULL ) + { + while( q && ( res != 0 ) && (!found) ) + { + ast_pthread_mutex_lock(&q->lock); + if( strcmp( q->name, queuename) == 0 ) + { + // found queue, try to enable interface + found=1 ; + + if( interface_exists( q, interface ) == NULL ) + { + save = q->members ; + q->members = create_queue_node( interface ) ; + + if( q->members != NULL ) + q->members->next = save ; + else + q->members = save ; + + ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename); + res = 0 ; + } + else + ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': " + "Already there\n", interface, queuename); + } + + ast_pthread_mutex_unlock(&q->lock); + q = q->next; + } + } + + if( ! found ) + ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", queuename); + + LOCAL_USER_REMOVE(u); + return res; +} + + static int queue_exec(struct ast_channel *chan, void *data) { int res=-1; @@ -936,10 +1178,15 @@ if (!res) { ast_cli_register(&cli_show_queues); ast_manager_register( "Queues", 0, manager_queues_show, "Queues" ); + + // [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) ; } reload_queues(); return res; } + int reload(void) {