Version 0.3.0 from FTP
authorMark Spencer <markster@digium.com>
Tue, 28 Jan 2003 22:33:41 +0000 (22:33 +0000)
committerMark Spencer <markster@digium.com>
Tue, 28 Jan 2003 22:33:41 +0000 (22:33 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@592 65c4cc65-6c06-0410-ace0-fbb531ad65f3

manager.c

index 365fb32..c5f5738 100755 (executable)
--- a/manager.c
+++ b/manager.c
@@ -51,29 +51,31 @@ static struct permalias {
        { -1, "all" },
 };
 
        { -1, "all" },
 };
 
-#define MAX_HEADERS 80
-#define MAX_LEN 256
+static struct mansession *sessions = NULL;
+static struct manager_action *first_action = NULL;
+static pthread_mutex_t actionlock = AST_MUTEX_INITIALIZER;
 
 
-static struct mansession {
-       pthread_t t;
-       pthread_mutex_t lock;
-       struct sockaddr_in sin;
-       int fd;
-       char username[80];
-       int authenticated;
-       int readperm;
-       int writeperm;
-       char inbuf[MAX_LEN];
-       int inlen;
-       
-       struct mansession *next;
-} *sessions = NULL;
+static int handle_showmancmds(int fd, int argc, char *argv[])
+{
+       struct manager_action *cur = first_action;
 
 
+       ast_pthread_mutex_lock(&actionlock);
+       while(cur) { /* Walk the list of actions */
+               ast_cli(fd, "\t%s  %s\r\n",cur->action, cur->synopsis);
+               cur = cur->next;
+       }
 
 
-struct message {
-       int hdrcount;
-       char headers[MAX_HEADERS][MAX_LEN];
-};
+       ast_pthread_mutex_unlock(&actionlock);
+       return RESULT_SUCCESS;
+}
+
+static char showmancmds_help[] = 
+"Usage: show manager commands\n"
+"      Prints a listing of all the available manager commands.\n";
+
+static struct ast_cli_entry show_mancmds_cli =
+       { { "show", "manager", "commands", NULL },
+       handle_showmancmds, "Show manager commands", showmancmds_help };
 
 static void destroy_session(struct mansession *s)
 {
 
 static void destroy_session(struct mansession *s)
 {
@@ -141,14 +143,18 @@ static int get_perm(char *instr)
        char *c;
        int x;
        int ret = 0;
        char *c;
        int x;
        int ret = 0;
+       char *stringp=NULL;
+       if (!instr)
+               return 0;
        strncpy(tmp, instr, sizeof(tmp) - 1);
        strncpy(tmp, instr, sizeof(tmp) - 1);
-       c = strtok(tmp, ",");
+       stringp=tmp;
+       c = strsep(&stringp, ",");
        while(c) {
                for (x=0;x<sizeof(perms) / sizeof(perms[0]);x++) {
                        if (!strcasecmp(perms[x].label, c)) 
                                ret |= perms[x].num;
                }
        while(c) {
                for (x=0;x<sizeof(perms) / sizeof(perms[0]);x++) {
                        if (!strcasecmp(perms[x].label, c)) 
                                ret |= perms[x].num;
                }
-               c = strtok(NULL, ",");
+               c = strsep(&stringp, ",");
        }
        return ret;
 }
        }
        return ret;
 }
@@ -300,6 +306,21 @@ static int action_redirect(struct mansession *s, struct message *m)
        return 0;
 }
 
        return 0;
 }
 
+static int action_command(struct mansession *s, struct message *m)
+{
+       char *cmd = get_header(m, "Command");
+       ast_pthread_mutex_lock(&s->lock);
+       s->blocking = 1;
+       ast_pthread_mutex_unlock(&s->lock);
+       ast_cli(s->fd, "Response: Follows\r\n");
+       ast_cli_command(s->fd, cmd);
+       ast_cli(s->fd, "--END COMMAND--\r\n\r\n");
+       ast_pthread_mutex_lock(&s->lock);
+       s->blocking = 0;
+       ast_pthread_mutex_unlock(&s->lock);
+       return 0;
+}
+
 static int action_originate(struct mansession *s, struct message *m)
 {
        char *name = get_header(m, "Channel");
 static int action_originate(struct mansession *s, struct message *m)
 {
        char *name = get_header(m, "Channel");
@@ -307,6 +328,7 @@ static int action_originate(struct mansession *s, struct message *m)
        char *context = get_header(m, "Context");
        char *priority = get_header(m, "Priority");
        char *timeout = get_header(m, "Timeout");
        char *context = get_header(m, "Context");
        char *priority = get_header(m, "Priority");
        char *timeout = get_header(m, "Timeout");
+       char *callerid = get_header(m, "CallerID");
        char *tech, *data;
        int pi = 0;
        int res;
        char *tech, *data;
        int pi = 0;
        int res;
@@ -321,7 +343,7 @@ static int action_originate(struct mansession *s, struct message *m)
                send_error(s, "Invalid priority\n");
                return 0;
        }
                send_error(s, "Invalid priority\n");
                return 0;
        }
-       if (strlen(timeout) && (sscanf(priority, "%d", &to) != 1)) {
+       if (strlen(timeout) && (sscanf(timeout, "%d", &to) != 1)) {
                send_error(s, "Invalid timeout\n");
                return 0;
        }
                send_error(s, "Invalid timeout\n");
                return 0;
        }
@@ -334,7 +356,7 @@ static int action_originate(struct mansession *s, struct message *m)
        }
        *data = '\0';
        data++;
        }
        *data = '\0';
        data++;
-       res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 0);
+       res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 0, strlen(callerid) ? callerid : NULL, NULL );
        if (!res)
                send_ack(s, "Originate successfully queued");
        else
        if (!res)
                send_ack(s, "Originate successfully queued");
        else
@@ -342,24 +364,13 @@ static int action_originate(struct mansession *s, struct message *m)
        return 0;
 }
 
        return 0;
 }
 
-static struct action {
-       char *action;
-       int authority;
-       int (*func)(struct mansession *s, struct message *m);
-} actions[] = {
-       { "Ping", 0, action_ping },
-       { "Logoff", 0, action_logoff },
-       { "Hangup", EVENT_FLAG_CALL, action_hangup },
-       { "Status", EVENT_FLAG_CALL, action_status },
-       { "Redirect", EVENT_FLAG_CALL, action_redirect },
-       { "Originate", EVENT_FLAG_CALL, action_originate },
-};
-
 static int process_message(struct mansession *s, struct message *m)
 {
 static int process_message(struct mansession *s, struct message *m)
 {
-       int x;
        char action[80];
        char action[80];
+       struct manager_action *tmp = first_action;
+
        strncpy(action, get_header(m, "Action"), sizeof(action));
        strncpy(action, get_header(m, "Action"), sizeof(action));
+
        if (!strlen(action)) {
                send_error(s, "Missing action in request");
                return 0;
        if (!strlen(action)) {
                send_error(s, "Missing action in request");
                return 0;
@@ -374,31 +385,26 @@ static int process_message(struct mansession *s, struct message *m)
                                s->authenticated = 1;
                                if (option_verbose > 1) 
                                        ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
                                s->authenticated = 1;
                                if (option_verbose > 1) 
                                        ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
-                               ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
+                               ast_log(LOG_EVENT, "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
                                send_ack(s, "Authentication accepted");
                        }
                } else 
                        send_error(s, "Authentication Required");
        } else {
                                send_ack(s, "Authentication accepted");
                        }
                } else 
                        send_error(s, "Authentication Required");
        } else {
-               for (x=0;x<sizeof(actions) / sizeof(actions[0]);x++) {
-                       if (!strcasecmp(action, actions[x].action)) {
-                               if ((s->writeperm & actions[x].authority) == actions[x].authority) {
-                                       if (actions[x].func(s, m))
+               while( tmp ) {          
+                       if (!strcasecmp(action, tmp->action)) {
+                               if ((s->writeperm & tmp->authority) == tmp->authority) {
+                                       if (tmp->func(s, m))
                                                return -1;
                                } else {
                                        send_error(s, "Permission denied");
                                }
                                                return -1;
                                } else {
                                        send_error(s, "Permission denied");
                                }
-                               break;
+                               return 0;
                        }
                        }
+                       tmp = tmp->next;
                }
                }
-               if (x >= sizeof(actions) / sizeof(actions[0]))
-                       send_error(s, "Invalid/unknown command");
-       }
-#if 0
-       for (x=0;x<m->hdrcount;x++) {
-               printf("Header: %s\n", m->headers[x]);
+               send_error(s, "Invalid/unknown command");
        }
        }
-#endif 
        return 0;
 }
 
        return 0;
 }
 
@@ -509,7 +515,7 @@ static void *accept_thread(void *ignore)
                if (pthread_create(&t, NULL, session_do, s))
                        destroy_session(s);
        }
                if (pthread_create(&t, NULL, session_do, s))
                        destroy_session(s);
        }
-               
+       return NULL;
 }
 
 int manager_event(int category, char *event, char *fmt, ...)
 }
 
 int manager_event(int category, char *event, char *fmt, ...)
@@ -523,12 +529,14 @@ int manager_event(int category, char *event, char *fmt, ...)
        while(s) {
                if ((s->readperm & category) == category) {
                        ast_pthread_mutex_lock(&s->lock);
        while(s) {
                if ((s->readperm & category) == category) {
                        ast_pthread_mutex_lock(&s->lock);
-                       ast_cli(s->fd, "Event: %s\r\n", event);
-                       va_start(ap, fmt);
-                       vsnprintf(tmp, sizeof(tmp), fmt, ap);
-                       va_end(ap);
-                       write(s->fd, tmp, strlen(tmp));
-                       ast_cli(s->fd, "\r\n");
+                       if (!s->blocking) {
+                               ast_cli(s->fd, "Event: %s\r\n", event);
+                               va_start(ap, fmt);
+                               vsnprintf(tmp, sizeof(tmp), fmt, ap);
+                               va_end(ap);
+                               write(s->fd, tmp, strlen(tmp));
+                               ast_cli(s->fd, "\r\n");
+                       }
                        ast_pthread_mutex_unlock(&s->lock);
                }
                s = s->next;
                        ast_pthread_mutex_unlock(&s->lock);
                }
                s = s->next;
@@ -537,6 +545,59 @@ int manager_event(int category, char *event, char *fmt, ...)
        return 0;
 }
 
        return 0;
 }
 
+int ast_manager_unregister( char *action ) {
+       struct manager_action *cur = first_action, *prev = first_action;
+
+       ast_pthread_mutex_lock(&actionlock);
+       while( cur ) {          
+               if (!strcasecmp(action, cur->action)) {
+                       prev->next = cur->next;
+                       free(cur);
+                       if (option_verbose > 1) 
+                               ast_verbose(VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action);
+                       ast_pthread_mutex_unlock(&actionlock);
+                       return 0;
+               }
+               prev = cur;
+               cur = cur->next;
+       }
+       ast_pthread_mutex_unlock(&actionlock);
+       return 0;
+}
+
+int ast_manager_register( char *action, int auth, 
+       int (*func)(struct mansession *s, struct message *m), char *synopsis)
+{
+       struct manager_action *cur = first_action, *prev = NULL;
+
+       ast_pthread_mutex_lock(&actionlock);
+       while(cur) { /* Walk the list of actions */
+               prev = cur; 
+               cur = cur->next;
+       }
+       cur = malloc( sizeof(struct manager_action) );
+       if( !cur ) {
+               ast_log(LOG_WARNING, "Manager: out of memory trying to register action\n");
+               ast_pthread_mutex_unlock(&actionlock);
+               return -1;
+       }
+       strncpy( cur->action, action, 255 );
+       cur->authority = auth;
+       cur->func = func;
+       cur->synopsis = synopsis;
+       cur->next = NULL;
+
+       if( prev ) prev->next = cur;
+       else first_action = cur;
+
+       if (option_verbose > 1) 
+               ast_verbose(VERBOSE_PREFIX_2 "Manager registered action %s\n", action);
+       ast_pthread_mutex_unlock(&actionlock);
+       return 0;
+}
+
+static int registered = 0;
+
 int init_manager(void)
 {
        struct ast_config *cfg;
 int init_manager(void)
 {
        struct ast_config *cfg;
@@ -544,7 +605,19 @@ int init_manager(void)
        int oldportno = portno;
        static struct sockaddr_in ba;
        int x = 1;
        int oldportno = portno;
        static struct sockaddr_in ba;
        int x = 1;
-
+       if (!registered) {
+               /* Register default actions */
+               ast_manager_register( "Ping", 0, action_ping, "Ping" );
+               ast_manager_register( "Logoff", 0, action_logoff, "Logoff Manager" );
+               ast_manager_register( "Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel" );
+               ast_manager_register( "Status", EVENT_FLAG_CALL, action_status, "Status" );
+               ast_manager_register( "Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect" );
+               ast_manager_register( "Originate", EVENT_FLAG_CALL, action_originate, "Originate Call" );
+               ast_manager_register( "Command", EVENT_FLAG_COMMAND, action_command, "Execute Command" );
+
+               ast_cli_register(&show_mancmds_cli);
+               registered = 1;
+       }
        portno = DEFAULT_MANAGER_PORT;
        cfg = ast_load("manager.conf");
        if (!cfg) {
        portno = DEFAULT_MANAGER_PORT;
        cfg = ast_load("manager.conf");
        if (!cfg) {