Merge dynamic queue support
authorMark Spencer <markster@digium.com>
Fri, 27 Jun 2003 23:07:59 +0000 (23:07 +0000)
committerMark Spencer <markster@digium.com>
Fri, 27 Jun 2003 23:07:59 +0000 (23:07 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1127 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_queue.c

index d983201..a513385 100755 (executable)
@@ -35,6 +35,8 @@
 #include <sys/signal.h>
 #include <netinet/in.h>
 
+#include <tonezone.h>
+
 #include <pthread.h>
 
 #define DEFAULT_RETRY          5
@@ -63,6 +65,28 @@ static char *descrip =
 "  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. */
@@ -643,6 +667,217 @@ static int valid_exit(struct queue_ent *qe, char digit)
        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;
@@ -944,11 +1179,16 @@ int load_module(void)
        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)
 {
        reload_queues();