Fri Sep 25 19:28:38 2009

Asterisk developer's documentation


manager.c File Reference

The Asterisk Management Interface - AMI. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/http.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"

Include dependency graph for manager.c:

Go to the source code of this file.

Data Structures

struct  ast_manager_user
struct  eventqent
struct  fast_originate_helper
struct  mansession
struct  permalias
struct  variable_count

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
#define MANAGER_EVENT_BUF_INITSIZE   256

Enumerations

enum  { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }

Functions

static void * accept_thread (void *ignore)
static int action_command (struct mansession *s, const struct message *m)
 action_command: Manager command "command" - execute CLI command
static int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
static int action_getconfig (struct mansession *s, const struct message *m)
static int action_getvar (struct mansession *s, const struct message *m)
static int action_hangup (struct mansession *s, const struct message *m)
static int action_listcommands (struct mansession *s, const struct message *m)
static int action_logoff (struct mansession *s, const struct message *m)
static int action_mailboxcount (struct mansession *s, const struct message *m)
static int action_mailboxstatus (struct mansession *s, const struct message *m)
static int action_message (struct mansession *s, const struct message *m)
static int action_originate (struct mansession *s, const struct message *m)
static int action_ping (struct mansession *s, const struct message *m)
static int action_redirect (struct mansession *s, const struct message *m)
 action_redirect: The redirect manager command
static int action_setvar (struct mansession *s, const struct message *m)
static int action_status (struct mansession *s, const struct message *m)
 Manager "status" command to show channels.
static int action_timeout (struct mansession *s, const struct message *m)
static int action_updateconfig (struct mansession *s, const struct message *m)
static int action_userevent (struct mansession *s, const struct message *m)
static int action_waitevent (struct mansession *s, const struct message *m)
static int append_event (const char *str, int category)
static struct ast_manager_userast_get_manager_by_name_locked (const char *name)
static int ast_instring (const char *bigstr, const char *smallstr, char delim)
static int ast_is_number (const char *string)
static AST_LIST_HEAD_STATIC (users, ast_manager_user)
static AST_LIST_HEAD_STATIC (sessions, mansession)
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
 register a new command with manager, including online help. This is the preferred way to register a manager command
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 AST_RWLOCK_DEFINE_STATIC (actionlock)
 AST_THREADSTORAGE (astman_append_buf, astman_append_buf_init)
 AST_THREADSTORAGE (manager_event_buf, manager_event_buf_init)
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
struct ast_variableastman_get_variables (const struct message *m)
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
void astman_send_error (struct mansession *s, const struct message *m, char *error)
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
int astman_verify_session_readpermissions (unsigned long ident, int perm)
 Verify a session's read permissions against a permission mask.
int astman_verify_session_writepermissions (unsigned long ident, int perm)
 Verify a session's write permissions against a permission mask.
static int authenticate (struct mansession *s, const struct message *m)
static char * authority_to_str (int authority, char *res, int reslen)
 Convert authority code to string with serveral options.
static char * complete_show_mancmd (const char *line, const char *word, int pos, int state)
static int compress_char (char c)
static void destroy_session (struct mansession *s)
static int do_message (struct mansession *s)
static void * fast_originate (void *data)
static struct mansessionfind_session (unsigned long ident)
static void free_session (struct mansession *s)
static char * generic_http_callback (int format, struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int get_input (struct mansession *s, char *output)
static int get_perm (const char *instr)
static int handle_showmanager (int fd, int argc, char *argv[])
static int handle_showmanagers (int fd, int argc, char *argv[])
static int handle_showmancmd (int fd, int argc, char *argv[])
static int handle_showmancmds (int fd, int argc, char *argv[])
 CLI command Should change to "manager show commands".
static int handle_showmanconn (int fd, int argc, char *argv[])
 CLI command show manager connected.
static int handle_showmaneventq (int fd, int argc, char *argv[])
 CLI command show manager connected.
static void handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg)
static char * html_translate (char *in)
int init_manager (void)
int manager_event (int category, const char *event, const char *fmt,...)
 manager_event: Send AMI event to client
static char * manager_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int manager_state_cb (char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
static char * mxml_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
static char * rawman_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
int reload_manager (void)
static void * session_do (void *data)
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static void unuse_eventqent (struct eventqent *e)
static int variable_count_cmp_fn (void *obj, void *vstr, int flags)
static int variable_count_hash_fn (const void *vvc, const int flags)
static void xml_copy_escape (char **dst, size_t *maxlen, const char *src, int lower)
static char * xml_translate (char *in, struct ast_variable *vars)

Variables

static int asock = -1
static int block_sockets
static struct ast_cli_entry cli_manager []
static struct ast_cli_entry cli_show_manager_command_deprecated
static struct ast_cli_entry cli_show_manager_commands_deprecated
static struct ast_cli_entry cli_show_manager_connected_deprecated
static struct ast_cli_entry cli_show_manager_eventq_deprecated
static const char * command_blacklist []
static char * contenttype [] = { "plain", "html", "xml" }
static int displayconnects = 1
static int enabled
static struct manager_actionfirst_action
static int httptimeout = 60
struct ast_http_uri manageruri
struct ast_http_uri managerxmluri
static char mandescr_command []
static char mandescr_events []
static char mandescr_extensionstate []
static char mandescr_getconfig []
static char mandescr_getvar []
static char mandescr_hangup []
static char mandescr_listcommands []
static char mandescr_logoff []
static char mandescr_mailboxcount []
static char mandescr_mailboxstatus []
 Help text for manager command mailboxstatus.
static char mandescr_message []
static char mandescr_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_setvar []
static char mandescr_timeout []
static char mandescr_updateconfig []
static char mandescr_userevent []
static char mandescr_waitevent []
 Manager WAITEVENT.
struct eventqentmaster_eventq = NULL
static int num_sessions
static struct permalias perms []
static int portno = DEFAULT_MANAGER_PORT
struct ast_http_uri rawmanuri
static int registered = 0
static char showmanager_help []
static char showmanagers_help []
static char showmancmd_help []
static char showmancmds_help []
static char showmanconn_help []
static char showmaneventq_help []
static pthread_t t
static int timestampevents
static int webregged = 0


Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
Channel Management and more

manager.conf

Definition in file manager.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 2714 of file manager.c.

02714      {
02715    FORMAT_RAW,
02716    FORMAT_HTML,
02717    FORMAT_XML,
02718 };


Function Documentation

int astman_verify_session_readpermissions ( unsigned long  ident,
int  perm 
)

Verify a session's read permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2676 of file manager.c.

References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, mansession::readperm, and s.

02677 {
02678    int result = 0;
02679    struct mansession *s;
02680 
02681    AST_LIST_LOCK(&sessions);
02682    AST_LIST_TRAVERSE(&sessions, s, list) {
02683       ast_mutex_lock(&s->__lock);
02684       if ((s->managerid == ident) && (s->readperm & perm)) {
02685          result = 1;
02686          ast_mutex_unlock(&s->__lock);
02687          break;
02688       }
02689       ast_mutex_unlock(&s->__lock);
02690    }
02691    AST_LIST_UNLOCK(&sessions);
02692    return result;
02693 }

int astman_verify_session_writepermissions ( unsigned long  ident,
int  perm 
)

Verify a session's write permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2695 of file manager.c.

References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, s, and mansession::writeperm.

02696 {
02697    int result = 0;
02698    struct mansession *s;
02699 
02700    AST_LIST_LOCK(&sessions);
02701    AST_LIST_TRAVERSE(&sessions, s, list) {
02702       ast_mutex_lock(&s->__lock);
02703       if ((s->managerid == ident) && (s->writeperm & perm)) {
02704          result = 1;
02705          ast_mutex_unlock(&s->__lock);
02706          break;
02707       }
02708       ast_mutex_unlock(&s->__lock);
02709    }
02710    AST_LIST_UNLOCK(&sessions);
02711    return result;
02712 }

static struct mansession* find_session ( unsigned long  ident  )  [static, read]

END Doxygen group

Definition at line 2658 of file manager.c.

References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::inuse, mansession::managerid, mansession::needdestroy, s, and mansession::sessiontimeout.

Referenced by generic_http_callback().

02659 {
02660    struct mansession *s;
02661 
02662    AST_LIST_LOCK(&sessions);
02663    AST_LIST_TRAVERSE(&sessions, s, list) {
02664       ast_mutex_lock(&s->__lock);
02665       if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
02666          s->inuse++;
02667          break;
02668       }
02669       ast_mutex_unlock(&s->__lock);
02670    }
02671    AST_LIST_UNLOCK(&sessions);
02672 
02673    return s;
02674 }

static char* generic_http_callback ( int  format,
struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Note:
There is approximately a 1 in 1.8E19 chance that the following calculation will produce 0, which is an invalid ID, but due to the properties of the rand() function (and the constantcy of s), that won't happen twice in a row.

Definition at line 2721 of file manager.c.

References mansession::__lock, ast_build_string(), ast_calloc, ast_http_error(), ast_http_setcookie(), ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_MAX_MANHEADERS, ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_verbose(), mansession::authenticated, destroy_session(), mansession::fd, find_session(), FORMAT_HTML, FORMAT_XML, free, message::hdrcount, message::headers, html_translate(), mansession::inuse, len, LOG_DEBUG, LOG_EVENT, malloc, mansession::managerid, ast_variable::name, mansession::needdestroy, eventqent::next, ast_variable::next, option_verbose, mansession::outputstr, process_message(), s, mansession::send_events, mansession::sessiontimeout, mansession::sin, strdup, mansession::username, ast_variable::value, VERBOSE_PREFIX_2, mansession::waiting_thread, and xml_translate().

Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().

02722 {
02723    struct mansession *s = NULL;
02724    unsigned long ident = 0;
02725    char workspace[512];
02726    char cookie[128];
02727    size_t len = sizeof(workspace);
02728    int blastaway = 0;
02729    char *c = workspace;
02730    char *retval = NULL;
02731    struct ast_variable *v;
02732 
02733    for (v = params; v; v = v->next) {
02734       if (!strcasecmp(v->name, "mansession_id")) {
02735          sscanf(v->value, "%lx", &ident);
02736          break;
02737       }
02738    }
02739    
02740    if (!(s = find_session(ident))) {
02741       /* Create new session */
02742       if (!(s = ast_calloc(1, sizeof(*s)))) {
02743          *status = 500;
02744          goto generic_callback_out;
02745       }
02746       memcpy(&s->sin, requestor, sizeof(s->sin));
02747       s->fd = -1;
02748       s->waiting_thread = AST_PTHREADT_NULL;
02749       s->send_events = 0;
02750       ast_mutex_init(&s->__lock);
02751       ast_mutex_lock(&s->__lock);
02752       s->inuse = 1;
02753                 /*!\note There is approximately a 1 in 1.8E19 chance that the following
02754                 * calculation will produce 0, which is an invalid ID, but due to the
02755                 * properties of the rand() function (and the constantcy of s), that
02756                 * won't happen twice in a row.
02757                  */
02758                 while ((s->managerid = rand() ^ (unsigned long) s) == 0);
02759       AST_LIST_LOCK(&sessions);
02760       AST_LIST_INSERT_HEAD(&sessions, s, list);
02761       /* Hook into the last spot in the event queue */
02762       s->eventq = master_eventq;
02763       while (s->eventq->next)
02764          s->eventq = s->eventq->next;
02765       ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
02766       ast_atomic_fetchadd_int(&num_sessions, 1);
02767       AST_LIST_UNLOCK(&sessions);
02768    }
02769 
02770    /* Reset HTTP timeout.  If we're not yet authenticated, keep it extremely short */
02771    time(&s->sessiontimeout);
02772    if (!s->authenticated && (httptimeout > 5))
02773       s->sessiontimeout += 5;
02774    else
02775       s->sessiontimeout += httptimeout;
02776    ast_mutex_unlock(&s->__lock);
02777    
02778    if (s) {
02779       struct message m = { 0 };
02780       char tmp[80];
02781       unsigned int x;
02782       size_t hdrlen;
02783 
02784       for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
02785          hdrlen = strlen(v->name) + strlen(v->value) + 3;
02786          m.headers[m.hdrcount] = alloca(hdrlen);
02787          snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
02788          m.hdrcount = x + 1;
02789       }
02790 
02791       if (process_message(s, &m)) {
02792          if (s->authenticated) {
02793             if (option_verbose > 1) {
02794                if (displayconnects) 
02795                   ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));    
02796             }
02797             ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02798          } else {
02799             if (option_verbose > 1) {
02800                if (displayconnects)
02801                   ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
02802             }
02803             ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
02804          }
02805          s->needdestroy = 1;
02806       }
02807       ast_build_string(&c, &len, "Content-type: text/%s\r\n", contenttype[format]);
02808       sprintf(tmp, "%08lx", s->managerid);
02809       ast_build_string(&c, &len, "%s\r\n", ast_http_setcookie("mansession_id", tmp, httptimeout, cookie, sizeof(cookie)));
02810       if (format == FORMAT_HTML)
02811          ast_build_string(&c, &len, "<title>Asterisk&trade; Manager Interface</title>");
02812       if (format == FORMAT_XML) {
02813          ast_build_string(&c, &len, "<ajax-response>\n");
02814       } else if (format == FORMAT_HTML) {
02815          ast_build_string(&c, &len, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
02816          ast_build_string(&c, &len, "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\"><h1>&nbsp;&nbsp;Manager Tester</h1></td></tr>\r\n");
02817       }
02818       ast_mutex_lock(&s->__lock);
02819       if (s->outputstr) {
02820          char *tmp;
02821          if (format == FORMAT_XML)
02822             tmp = xml_translate(s->outputstr->str, params);
02823          else if (format == FORMAT_HTML)
02824             tmp = html_translate(s->outputstr->str);
02825          else
02826             tmp = s->outputstr->str;
02827          if (tmp) {
02828             retval = malloc(strlen(workspace) + strlen(tmp) + 128);
02829             if (retval) {
02830                strcpy(retval, workspace);
02831                strcpy(retval + strlen(retval), tmp);
02832                c = retval + strlen(retval);
02833                len = 120;
02834             }
02835          }
02836          if (tmp != s->outputstr->str)
02837             free(tmp);
02838          free(s->outputstr);
02839          s->outputstr = NULL;
02840       }
02841       ast_mutex_unlock(&s->__lock);
02842       /* Still okay because c would safely be pointing to workspace even
02843          if retval failed to allocate above */
02844       if (format == FORMAT_XML) {
02845          ast_build_string(&c, &len, "</ajax-response>\n");
02846       } else if (format == FORMAT_HTML)
02847          ast_build_string(&c, &len, "</table></body>\r\n");
02848    } else {
02849       *status = 500;
02850       *title = strdup("Server Error");
02851    }
02852    ast_mutex_lock(&s->__lock);
02853    if (s->needdestroy) {
02854       if (s->inuse == 1) {
02855          ast_log(LOG_DEBUG, "Need destroy, doing it now!\n");
02856          blastaway = 1;
02857       } else {
02858          ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n");
02859          if (s->waiting_thread != AST_PTHREADT_NULL)
02860             pthread_kill(s->waiting_thread, SIGURG);
02861          s->inuse--;
02862       }
02863    } else
02864       s->inuse--;
02865    ast_mutex_unlock(&s->__lock);
02866    
02867    if (blastaway)
02868       destroy_session(s);
02869 generic_callback_out:
02870    if (*status != 200)
02871       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 
02872    return retval;
02873 }

int init_manager ( void   ) 

Called by Asterisk initialization

Definition at line 2914 of file manager.c.

References accept_thread(), action_command(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_message(), action_originate(), action_ping(), action_redirect(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), append_event(), ast_calloc, ast_category_browse(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_extension_state_add(), ast_get_manager_by_name_locked(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_manager_register, ast_manager_register2(), ast_pthread_create_background, ast_strdup, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), DEFAULT_MANAGER_PORT, ast_manager_user::deny, ast_manager_user::displayconnects, errno, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_USER, ast_channel::flags, free, ast_manager_user::keep, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_state_cb(), ast_variable::name, ast_variable::next, option_verbose, ast_manager_user::permit, ast_manager_user::read, ast_manager_user::secret, ast_manager_user::username, users, ast_variable::value, var, and ast_manager_user::write.

Referenced by main(), and reload_manager().

02915 {
02916    struct ast_config *cfg = NULL;
02917    const char *val;
02918    char *cat = NULL;
02919    int oldportno = portno;
02920    static struct sockaddr_in ba;
02921    int x = 1;
02922    int flags;
02923    int webenabled = 0;
02924    int newhttptimeout = 60;
02925    struct ast_manager_user *user = NULL;
02926 
02927    if (!registered) {
02928       /* Register default actions */
02929       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
02930       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
02931       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
02932       ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
02933       ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
02934       ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
02935       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
02936       ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
02937       ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
02938       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
02939       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
02940       ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
02941       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
02942       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
02943       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
02944       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
02945       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
02946       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
02947       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
02948       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
02949 
02950       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
02951       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
02952       registered = 1;
02953       /* Append placeholder event so master_eventq never runs dry */
02954       append_event("Event: Placeholder\r\n\r\n", 0);
02955    }
02956    portno = DEFAULT_MANAGER_PORT;
02957    displayconnects = 1;
02958    cfg = ast_config_load("manager.conf");
02959    if (!cfg) {
02960       ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
02961       return 0;
02962    }
02963    val = ast_variable_retrieve(cfg, "general", "enabled");
02964    if (val)
02965       enabled = ast_true(val);
02966 
02967    val = ast_variable_retrieve(cfg, "general", "block-sockets");
02968    if (val)
02969       block_sockets = ast_true(val);
02970 
02971    val = ast_variable_retrieve(cfg, "general", "webenabled");
02972    if (val)
02973       webenabled = ast_true(val);
02974 
02975    if ((val = ast_variable_retrieve(cfg, "general", "port"))) {
02976       if (sscanf(val, "%d", &portno) != 1) {
02977          ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
02978          portno = DEFAULT_MANAGER_PORT;
02979       }
02980    }
02981 
02982    if ((val = ast_variable_retrieve(cfg, "general", "displayconnects")))
02983       displayconnects = ast_true(val);
02984 
02985    if ((val = ast_variable_retrieve(cfg, "general", "timestampevents")))
02986       timestampevents = ast_true(val);
02987 
02988    if ((val = ast_variable_retrieve(cfg, "general", "httptimeout")))
02989       newhttptimeout = atoi(val);
02990 
02991    memset(&ba, 0, sizeof(ba));
02992    ba.sin_family = AF_INET;
02993    ba.sin_port = htons(portno);
02994 
02995    if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
02996       if (!inet_aton(val, &ba.sin_addr)) { 
02997          ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
02998          memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
02999       }
03000    }
03001    
03002 
03003    if ((asock > -1) && ((portno != oldportno) || !enabled)) {
03004 #if 0
03005       /* Can't be done yet */
03006       close(asock);
03007       asock = -1;
03008 #else
03009       ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
03010 #endif
03011    }
03012 
03013    AST_LIST_LOCK(&users);
03014 
03015    while ((cat = ast_category_browse(cfg, cat))) {
03016       struct ast_variable *var = NULL;
03017 
03018       if (!strcasecmp(cat, "general"))
03019          continue;
03020 
03021       /* Look for an existing entry, if none found - create one and add it to the list */
03022       if (!(user = ast_get_manager_by_name_locked(cat))) {
03023          if (!(user = ast_calloc(1, sizeof(*user))))
03024             break;
03025          /* Copy name over */
03026          ast_copy_string(user->username, cat, sizeof(user->username));
03027          /* Insert into list */
03028          AST_LIST_INSERT_TAIL(&users, user, list);
03029       }
03030 
03031       /* Make sure we keep this user and don't destroy it during cleanup */
03032       user->keep = 1;
03033 
03034       var = ast_variable_browse(cfg, cat);
03035       while (var) {
03036          if (!strcasecmp(var->name, "secret")) {
03037             if (user->secret)
03038                free(user->secret);
03039             user->secret = ast_strdup(var->value);
03040          } else if (!strcasecmp(var->name, "deny") ) {
03041             if (user->deny)
03042                free(user->deny);
03043             user->deny = ast_strdup(var->value);
03044          } else if (!strcasecmp(var->name, "permit") ) {
03045             if (user->permit)
03046                free(user->permit);
03047             user->permit = ast_strdup(var->value);
03048          }  else if (!strcasecmp(var->name, "read") ) {
03049             if (user->read)
03050                free(user->read);
03051             user->read = ast_strdup(var->value);
03052          }  else if (!strcasecmp(var->name, "write") ) {
03053             if (user->write)
03054                free(user->write);
03055             user->write = ast_strdup(var->value);
03056          }  else if (!strcasecmp(var->name, "displayconnects") )
03057             user->displayconnects = ast_true(var->value);
03058          else
03059             ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03060          var = var->next;
03061       }
03062    }
03063 
03064    /* Perform cleanup - essentially prune out old users that no longer exist */
03065    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03066       if (user->keep) {
03067          user->keep = 0;
03068          continue;
03069       }
03070       /* We do not need to keep this user so take them out of the list */
03071       AST_LIST_REMOVE_CURRENT(&users, list);
03072       /* Free their memory now */
03073       if (user->secret)
03074          free(user->secret);
03075       if (user->deny)
03076          free(user->deny);
03077       if (user->permit)
03078          free(user->permit);
03079       if (user->read)
03080          free(user->read);
03081       if (user->write)
03082          free(user->write);
03083       free(user);
03084    }
03085    AST_LIST_TRAVERSE_SAFE_END
03086 
03087    AST_LIST_UNLOCK(&users);
03088 
03089    ast_config_destroy(cfg);
03090    
03091    if (webenabled && enabled) {
03092       if (!webregged) {
03093          ast_http_uri_link(&rawmanuri);
03094          ast_http_uri_link(&manageruri);
03095          ast_http_uri_link(&managerxmluri);
03096          webregged = 1;
03097       }
03098    } else {
03099       if (webregged) {
03100          ast_http_uri_unlink(&rawmanuri);
03101          ast_http_uri_unlink(&manageruri);
03102          ast_http_uri_unlink(&managerxmluri);
03103          webregged = 0;
03104       }
03105    }
03106 
03107    if (newhttptimeout > 0)
03108       httptimeout = newhttptimeout;
03109 
03110    /* If not enabled, do nothing */
03111    if (!enabled)
03112       return 0;
03113 
03114    if (asock < 0) {
03115       asock = socket(AF_INET, SOCK_STREAM, 0);
03116       if (asock < 0) {
03117          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
03118          return -1;
03119       }
03120       setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
03121       if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
03122          ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
03123          close(asock);
03124          asock = -1;
03125          return -1;
03126       }
03127       if (listen(asock, 2)) {
03128          ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
03129          close(asock);
03130          asock = -1;
03131          return -1;
03132       }
03133       flags = fcntl(asock, F_GETFL);
03134       fcntl(asock, F_SETFL, flags | O_NONBLOCK);
03135       if (option_verbose)
03136          ast_verbose("Asterisk Management interface listening on port %d\n", portno);
03137       ast_pthread_create_background(&t, NULL, accept_thread, NULL);
03138    }
03139    return 0;
03140 }

static char* manager_http_callback ( struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 2875 of file manager.c.

References FORMAT_HTML, and generic_http_callback().

02876 {
02877    return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength);
02878 }

static char* mxml_http_callback ( struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 2880 of file manager.c.

References FORMAT_XML, and generic_http_callback().

02881 {
02882    return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength);
02883 }

static char* rawman_http_callback ( struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 2885 of file manager.c.

References FORMAT_RAW, and generic_http_callback().

02886 {
02887    return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength);
02888 }

int reload_manager ( void   ) 

Definition at line 3142 of file manager.c.

References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().

03143 {
03144    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03145    return init_manager();
03146 }


Variable Documentation

char* contenttype[] = { "plain", "html", "xml" } [static]

Definition at line 2719 of file manager.c.

Definition at line 2897 of file manager.c.

Definition at line 2904 of file manager.c.

Definition at line 2890 of file manager.c.

int registered = 0 [static]

Definition at line 2911 of file manager.c.

int webregged = 0 [static]

Definition at line 2912 of file manager.c.


Generated on Fri Sep 25 19:28:38 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.5