Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:36 2007

Asterisk developer's documentation :: Codename Pineapple


manager.c File Reference


Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
At the moment this file contains a number of functions, namely:

manager.conf

Definition in file manager.c.

#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 <sys/mman.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 dependency graph for manager.c:

Go to the source code of this file.

Data Structures

struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  eventqent
struct  fast_originate_helper
struct  mansession
struct  permalias

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MSG_MOREDATA   ((char *)astman_send_response)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
#define NEW_EVENT(m)   (AST_LIST_NEXT(m->last_ev, eq_next))
#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
#define TEST_STRING   "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"

Enumerations

enum  output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }

Functions

int __manager_event (int category, const char *event, const char *file, int line, const char *func, const char *fmt,...)
 manager_event: Send AMI event to client
static int action_challenge (struct mansession *s, const struct message *m)
static int action_command (struct mansession *s, const struct message *m)
 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_login (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_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_sendtext (struct mansession *s, const struct message *m)
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 int ast_instring (const char *bigstr, const char *smallstr, const char delim)
static AST_LIST_HEAD_STATIC (users, ast_manager_user)
 list of users found in the config file
static AST_LIST_HEAD_STATIC (sessions, mansession)
static AST_LIST_HEAD_STATIC (all_events, eventqent)
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
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired.
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
static AST_RWLIST_HEAD_STATIC (manager_hooks, manager_custom_hook)
 AST_RWLOCK_DEFINE_STATIC (actionlock)
 AST_THREADSTORAGE (manager_event_buf)
 AST_THREADSTORAGE (astman_append_buf)
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
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_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
static void astman_start_ack (struct mansession *s, const struct message *m)
static int authenticate (struct mansession *s, const struct message *m)
static char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static char * complete_show_mancmd (const char *line, const char *word, int pos, int state)
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 struct ast_strgeneric_http_callback (enum output_format 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 struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
 Event list management functions. We assume that the event list always has at least one element, and the delete code will not remove the last entry even if the.
static int handle_mandebug (int fd, int argc, char *argv[])
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 manager list commands.
static int handle_showmanconn (int fd, int argc, char *argv[])
 CLI command manager list connected.
static int handle_showmaneventq (int fd, int argc, char *argv[])
 CLI command manager list eventq.
static void handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg)
int init_manager (void)
static struct ast_strmanager_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)
static struct ast_strmxml_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 void purge_events (void)
static void purge_old_stuff (void *data)
 cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static struct ast_strrawman_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
static void ref_event (struct eventqent *e)
int reload_manager (void)
static int send_string (struct mansession *s, char *string)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
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 struct eventqentunref_event (struct eventqent *e)
static void xml_copy_escape (struct ast_str **out, const char *src, int mode)
static void xml_translate (struct ast_str **out, char *in, struct ast_variable *vars, enum output_format format)
 Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

Variables

static struct server_args ami_desc
tls_config ami_tls_cfg
static struct server_args amis_desc
static int block_sockets
static struct ast_cli_entry cli_manager []
static char * contenttype []
static int displayconnects = 1
static struct manager_actionfirst_action
 list of actions registered
static int httptimeout = 60
static int manager_debug
ast_http_uri manageruri
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_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_sendtext []
static char mandescr_setvar []
static char mandescr_timeout []
static char mandescr_updateconfig []
static char mandescr_userevent []
static char mandescr_waitevent []
 Manager WAITEVENT.
static int num_sessions
static struct permalias perms []
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 int timestampevents
static int webregged = 0


Define Documentation

#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
 

#define TEST_STRING   "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"
 


Enumeration Type Documentation

enum output_format
 

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 2483 of file manager.c.

02483                    {
02484    FORMAT_RAW,
02485    FORMAT_HTML,
02486    FORMAT_XML,
02487 };


Function Documentation

static struct mansession* find_session unsigned long  ident  )  [static]
 

locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket).

Definition at line 2500 of file manager.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions.

02501 {
02502    struct mansession *s;
02503 
02504    if (ident == 0)
02505       return NULL;
02506 
02507    AST_LIST_LOCK(&sessions);
02508    AST_LIST_TRAVERSE(&sessions, s, list) {
02509       ast_mutex_lock(&s->__lock);
02510       if (s->managerid == ident && !s->needdestroy) {
02511          ast_atomic_fetchadd_int(&s->inuse, 1);
02512          break;
02513       }
02514       ast_mutex_unlock(&s->__lock);
02515    }
02516    AST_LIST_UNLOCK(&sessions);
02517 
02518    return s;
02519 }

static struct ast_str* generic_http_callback enum output_format  format,
struct sockaddr_in *  requestor,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength
[static]
 

Definition at line 2705 of file manager.c.

References ast_variable::name, ast_variable::next, s, and ast_variable::value.

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

02709 {
02710    struct mansession *s = NULL;
02711    unsigned long ident = 0; /* invalid, so find_session will fail if not set through the cookie */
02712    int blastaway = 0;
02713    struct ast_variable *v;
02714    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
02715    struct ast_str *out = NULL;
02716    struct message m = { 0 };
02717    unsigned int x;
02718    size_t hdrlen;
02719 
02720    for (v = params; v; v = v->next) {
02721       if (!strcasecmp(v->name, "mansession_id")) {
02722          sscanf(v->value, "%lx", &ident);
02723          break;
02724       }
02725    }
02726 
02727    if (!(s = find_session(ident))) {
02728       /* Create new session.
02729        * While it is not in the list we don't need any locking
02730        */
02731       if (!(s = ast_calloc(1, sizeof(*s)))) {
02732          *status = 500;
02733          goto generic_callback_out;
02734       }
02735       s->sin = *requestor;
02736       s->fd = -1;
02737       s->waiting_thread = AST_PTHREADT_NULL;
02738       s->send_events = 0;
02739       ast_mutex_init(&s->__lock);
02740       ast_mutex_lock(&s->__lock);
02741       s->inuse = 1;
02742       s->managerid = rand() | 1; /* make sure it is non-zero */
02743       s->last_ev = grab_last();
02744       AST_LIST_LOCK(&sessions);
02745       AST_LIST_INSERT_HEAD(&sessions, s, list);
02746       AST_LIST_UNLOCK(&sessions);
02747       ast_atomic_fetchadd_int(&num_sessions, 1);
02748    }
02749 
02750    ast_mutex_unlock(&s->__lock);
02751 
02752    if (!(out = ast_str_create(1024))) {
02753       *status = 500;
02754       goto generic_callback_out;
02755    }
02756 
02757    s->fd = mkstemp(template); /* create a temporary file for command output */
02758    unlink(template);
02759    s->f = fdopen(s->fd, "w+");
02760 
02761    for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
02762       hdrlen = strlen(v->name) + strlen(v->value) + 3;
02763       m.headers[m.hdrcount] = alloca(hdrlen);
02764       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
02765       m.hdrcount = x + 1;
02766    }
02767 
02768    if (process_message(s, &m)) {
02769       if (s->authenticated) {
02770          if (option_verbose > 1) {
02771             if (displayconnects)
02772                ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02773          }
02774          ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02775       } else {
02776          if (option_verbose > 1) {
02777             if (displayconnects)
02778                ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
02779          }
02780          ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
02781       }
02782       s->needdestroy = 1;
02783    }
02784 
02785    ast_str_append(&out, 0,
02786              "Content-type: text/%s\r\n"
02787              "Cache-Control: no-cache;\r\n"
02788              "Set-Cookie: mansession_id=\"%08lx\"; Version=\"1\"; Max-Age=%d\r\n"
02789              "\r\n",
02790          contenttype[format],
02791          s->managerid, httptimeout);
02792 
02793    if (format == FORMAT_XML) {
02794       ast_str_append(&out, 0, "<ajax-response>\n");
02795    } else if (format == FORMAT_HTML) {
02796 
02797 #define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
02798 #define TEST_STRING \
02799    "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \
02800    user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \
02801    <input type=\"submit\"></form>"
02802 
02803       ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
02804       ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
02805       ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
02806       ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
02807    }
02808 
02809    if (s->f != NULL) {  /* have temporary output */
02810       char *buf;
02811       size_t l = ftell(s->f);
02812 
02813       if (format == FORMAT_XML || format == FORMAT_HTML) {
02814          if (l) {
02815             if ((buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0))) {
02816                xml_translate(&out, buf, params, format);
02817                munmap(buf, l);
02818             }
02819          } else {
02820             xml_translate(&out, "", params, format);
02821          }
02822       }
02823       fclose(s->f);
02824       s->f = NULL;
02825       s->fd = -1;
02826    }
02827 
02828    if (format == FORMAT_XML) {
02829       ast_str_append(&out, 0, "</ajax-response>\n");
02830    } else if (format == FORMAT_HTML)
02831       ast_str_append(&out, 0, "</table></body>\r\n");
02832 
02833    ast_mutex_lock(&s->__lock);
02834    /* Reset HTTP timeout.  If we're not authenticated, keep it extremely short */
02835    s->sessiontimeout = time(NULL) + ((s->authenticated || httptimeout < 5) ? httptimeout : 5);
02836 
02837    if (s->needdestroy) {
02838       if (s->inuse == 1) {
02839          if (option_debug)
02840             ast_log(LOG_DEBUG, "Need destroy, doing it now!\n");
02841          blastaway = 1;
02842       } else {
02843          if (option_debug)
02844             ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n");
02845          if (s->waiting_thread != AST_PTHREADT_NULL)
02846             pthread_kill(s->waiting_thread, SIGURG);
02847          s->inuse--;
02848       }
02849    } else
02850       s->inuse--;
02851    ast_mutex_unlock(&s->__lock);
02852 
02853    if (blastaway)
02854       destroy_session(s);
02855 generic_callback_out:
02856    if (*status != 200)
02857       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
02858    return out;
02859 }

int init_manager void   ) 
 

Called by Asterisk initialization

Definition at line 2931 of file manager.c.

References action_challenge(), action_command(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ahp, ami_desc, ami_tls_cfg, amis_desc, append_event(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_load(), ast_extension_state_add(), ast_gethostbyname(), ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), tls_config::certfile, tls_config::cipher, cli_manager, DEFAULT_MANAGER_PORT, enabled, tls_config::enabled, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_USER, free, hp, LOG_NOTICE, manager_state_cb(), mandescr_command, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getvar, mandescr_hangup, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_sendtext, mandescr_setvar, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, server_args::sin, and var.

Referenced by reload_manager().

02932 {
02933    struct ast_config *cfg = NULL;
02934    const char *val;
02935    char *cat = NULL;
02936    int webenabled = 0;
02937    int enabled = 0;
02938    int newhttptimeout = 60;
02939    int have_sslbindaddr = 0;
02940    struct hostent *hp;
02941    struct ast_hostent ahp;
02942    struct ast_manager_user *user = NULL;
02943    struct ast_variable *var;
02944 
02945    if (!registered) {
02946       /* Register default actions */
02947       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
02948       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
02949       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
02950       ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
02951       ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
02952       ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
02953       ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
02954       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
02955       ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
02956       ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
02957       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
02958       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
02959       ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
02960       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
02961       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
02962       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
02963       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
02964       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
02965       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
02966       ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
02967       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
02968       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
02969 
02970       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
02971       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
02972       registered = 1;
02973       /* Append placeholder event so master_eventq never runs dry */
02974       append_event("Event: Placeholder\r\n\r\n", 0);
02975    }
02976    displayconnects = 1;
02977    cfg = ast_config_load("manager.conf");
02978    if (!cfg) {
02979       ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
02980       return 0;
02981    }
02982 
02983    /* default values */
02984    memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in));
02985    memset(&amis_desc.sin, 0, sizeof(amis_desc.sin));
02986    amis_desc.sin.sin_port = htons(5039);
02987    ami_desc.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
02988 
02989    ami_tls_cfg.enabled = 0;
02990    if (ami_tls_cfg.certfile)
02991       free(ami_tls_cfg.certfile);
02992    ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
02993    if (ami_tls_cfg.cipher)
02994       free(ami_tls_cfg.cipher);
02995    ami_tls_cfg.cipher = ast_strdup("");
02996 
02997    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02998       val = var->value;
02999       if (!strcasecmp(var->name, "ssenable"))
03000          ami_tls_cfg.enabled = ast_true(val);
03001       else if (!strcasecmp(var->name, "ssbindport"))
03002          amis_desc.sin.sin_port = htons(atoi(val));
03003       else if (!strcasecmp(var->name, "ssbindaddr")) {
03004          if ((hp = ast_gethostbyname(val, &ahp))) {
03005             memcpy(&amis_desc.sin.sin_addr, hp->h_addr, sizeof(amis_desc.sin.sin_addr));
03006             have_sslbindaddr = 1;
03007          } else {
03008             ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
03009          }
03010       } else if (!strcasecmp(var->name, "sslcert")) {
03011          free(ami_tls_cfg.certfile);
03012          ami_tls_cfg.certfile = ast_strdup(val);
03013       } else if (!strcasecmp(var->name, "sslcipher")) {
03014          free(ami_tls_cfg.cipher);
03015          ami_tls_cfg.cipher = ast_strdup(val);
03016       } else if (!strcasecmp(var->name, "enabled")) {
03017          enabled = ast_true(val);
03018       } else if (!strcasecmp(var->name, "block-sockets")) {
03019          block_sockets = ast_true(val);
03020       } else if (!strcasecmp(var->name, "webenabled")) {
03021          webenabled = ast_true(val);
03022       } else if (!strcasecmp(var->name, "port")) {
03023          ami_desc.sin.sin_port = htons(atoi(val));
03024       } else if (!strcasecmp(var->name, "bindaddr")) {
03025          if (!inet_aton(val, &ami_desc.sin.sin_addr)) {
03026             ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03027             memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr));
03028          }
03029       } else if (!strcasecmp(var->name, "displayconnects")) {
03030          displayconnects = ast_true(val);
03031       } else if (!strcasecmp(var->name, "timestampevents")) {
03032          timestampevents = ast_true(val);
03033       } else if (!strcasecmp(var->name, "debug")) {
03034          manager_debug = ast_true(val);
03035       } else if (!strcasecmp(var->name, "httptimeout")) {
03036          newhttptimeout = atoi(val);
03037       } else {
03038          ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
03039             var->name, val);
03040       }  
03041    }
03042 
03043    if (enabled)
03044       ami_desc.sin.sin_family = AF_INET;
03045    if (!have_sslbindaddr)
03046       amis_desc.sin.sin_addr = ami_desc.sin.sin_addr;
03047    if (ami_tls_cfg.enabled)
03048       amis_desc.sin.sin_family = AF_INET;
03049 
03050    
03051    AST_LIST_LOCK(&users);
03052 
03053    while ((cat = ast_category_browse(cfg, cat))) {
03054 
03055       if (!strcasecmp(cat, "general"))
03056          continue;
03057 
03058       /* Look for an existing entry, if none found - create one and add it to the list */
03059       if (!(user = get_manager_by_name_locked(cat))) {
03060          if (!(user = ast_calloc(1, sizeof(*user))))
03061             break;
03062          /* Copy name over */
03063          ast_copy_string(user->username, cat, sizeof(user->username));
03064          /* Insert into list */
03065          AST_LIST_INSERT_TAIL(&users, user, list);
03066       }
03067 
03068       /* Make sure we keep this user and don't destroy it during cleanup */
03069       user->keep = 1;
03070 
03071       var = ast_variable_browse(cfg, cat);
03072       while (var) {
03073          if (!strcasecmp(var->name, "secret")) {
03074             if (user->secret)
03075                free(user->secret);
03076             user->secret = ast_strdup(var->value);
03077          } else if (!strcasecmp(var->name, "deny") ) {
03078             if (user->deny)
03079                free(user->deny);
03080             user->deny = ast_strdup(var->value);
03081          } else if (!strcasecmp(var->name, "permit") ) {
03082             if (user->permit)
03083                free(user->permit);
03084             user->permit = ast_strdup(var->value);
03085          }  else if (!strcasecmp(var->name, "read") ) {
03086             if (user->read)
03087                free(user->read);
03088             user->read = ast_strdup(var->value);
03089          }  else if (!strcasecmp(var->name, "write") ) {
03090             if (user->write)
03091                free(user->write);
03092             user->write = ast_strdup(var->value);
03093          }  else if (!strcasecmp(var->name, "displayconnects") )
03094             user->displayconnects = ast_true(var->value);
03095          else {
03096             if (option_debug)
03097                ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03098          }
03099          var = var->next;
03100       }
03101    }
03102 
03103    /* Perform cleanup - essentially prune out old users that no longer exist */
03104    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03105       if (user->keep) { /* valid record. clear flag for the next round */
03106          user->keep = 0;
03107          continue;
03108       }
03109       /* We do not need to keep this user so take them out of the list */
03110       AST_LIST_REMOVE_CURRENT(&users, list);
03111       /* Free their memory now */
03112       if (user->secret)
03113          free(user->secret);
03114       if (user->deny)
03115          free(user->deny);
03116       if (user->permit)
03117          free(user->permit);
03118       if (user->read)
03119          free(user->read);
03120       if (user->write)
03121          free(user->write);
03122       free(user);
03123    }
03124    AST_LIST_TRAVERSE_SAFE_END
03125 
03126    AST_LIST_UNLOCK(&users);
03127 
03128    ast_config_destroy(cfg);
03129 
03130    if (webenabled && enabled) {
03131       if (!webregged) {
03132          ast_http_uri_link(&rawmanuri);
03133          ast_http_uri_link(&manageruri);
03134          ast_http_uri_link(&managerxmluri);
03135          webregged = 1;
03136       }
03137    } else {
03138       if (webregged) {
03139          ast_http_uri_unlink(&rawmanuri);
03140          ast_http_uri_unlink(&manageruri);
03141          ast_http_uri_unlink(&managerxmluri);
03142          webregged = 0;
03143       }
03144    }
03145 
03146    if (newhttptimeout > 0)
03147       httptimeout = newhttptimeout;
03148 
03149    server_start(&ami_desc);
03150    if (ssl_setup(amis_desc.tls_cfg))
03151       server_start(&amis_desc);
03152    return 0;
03153 }

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

Definition at line 2861 of file manager.c.

References FORMAT_HTML, and generic_http_callback().

02862 {
02863    return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength);
02864 }

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

Definition at line 2866 of file manager.c.

References FORMAT_XML, and generic_http_callback().

02867 {
02868    return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength);
02869 }

static void purge_old_stuff void *  data  )  [static]
 

cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most

Definition at line 2903 of file manager.c.

References purge_events(), and purge_sessions().

02904 {
02905    purge_sessions(1);
02906    purge_events();
02907 }

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

Definition at line 2871 of file manager.c.

References FORMAT_RAW, and generic_http_callback().

02872 {
02873    return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength);
02874 }

int reload_manager void   ) 
 

Definition at line 3155 of file manager.c.

References EVENT_FLAG_SYSTEM, init_manager(), and manager_event.

03156 {
03157    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03158    return init_manager();
03159 }

static void xml_copy_escape struct ast_str **  out,
const char *  src,
int  mode
[static]
 

Definition at line 2526 of file manager.c.

References ast_str_append(), and space.

02527 {
02528    /* store in a local buffer to avoid calling ast_str_append too often */
02529    char buf[256];
02530    char *dst = buf;
02531    int space = sizeof(buf);
02532    /* repeat until done and nothing to flush */
02533    for ( ; *src || dst != buf ; src++) {
02534       if (*src == '\0' || space < 10) {   /* flush */
02535          *dst++ = '\0';
02536          ast_str_append(out, 0, "%s", buf);
02537          dst = buf;
02538          space = sizeof(buf);
02539          if (*src == '\0')
02540             break;
02541       }
02542          
02543       if ( (mode & 2) && !isalnum(*src)) {
02544          *dst++ = '_';
02545          space--;
02546          continue;
02547       }
02548       switch (*src) {
02549       case '<':
02550          strcpy(dst, "&lt;");
02551          dst += 4;
02552          space -= 4;
02553          break;
02554       case '>':
02555          strcpy(dst, "&gt;");
02556          dst += 4;
02557          space -= 4;
02558          break;
02559       case '\"':
02560          strcpy(dst, "&quot;");
02561          dst += 6;
02562          space -= 6;
02563          break;
02564       case '\'':
02565          strcpy(dst, "&apos;");
02566          dst += 6;
02567          space -= 6;
02568          break;
02569       case '&':
02570          strcpy(dst, "&amp;");
02571          dst += 5;
02572          space -= 5;
02573          break;
02574 
02575       default:
02576          *dst++ = mode ? tolower(*src) : *src;
02577          space--;
02578       }
02579    }
02580 }

static void xml_translate struct ast_str **  out,
char *  in,
struct ast_variable vars,
enum output_format  format
[static]
 

Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications):

General: the unformatted text is used as a value of XML output: to be completed Each section is within <response type="object" id="xxx"> where xxx is taken from ajaxdest variable or defaults to unknown Each row is reported as an attribute Name="value" of an XML entity named from the variable ajaxobjtype, default to "generic"

HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a


Definition at line 2607 of file manager.c.

References FORMAT_XML, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02608 {
02609    struct ast_variable *v;
02610    char *dest = NULL;
02611    char *var, *val;
02612    char *objtype = NULL;
02613    int in_data = 0;  /* parsing data */
02614    int inobj = 0;
02615    int xml = (format == FORMAT_XML);
02616 
02617    for (v = vars; v; v = v->next) {
02618       if (!dest && !strcasecmp(v->name, "ajaxdest"))
02619          dest = v->value;
02620       else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
02621          objtype = v->value;
02622    }
02623    if (!dest)
02624       dest = "unknown";
02625    if (!objtype)
02626       objtype = "generic";
02627 #if 0
02628    /* determine how large is the response.
02629     * This is a heuristic - counting colons (for headers),
02630     * newlines (for extra arguments), and escaped chars.
02631     * XXX needs to be checked carefully for overflows.
02632     * Even better, use some code that allows extensible strings.
02633     */
02634    for (x = 0; in[x]; x++) {
02635       if (in[x] == ':')
02636          colons++;
02637       else if (in[x] == '\n')
02638          breaks++;
02639       else if (strchr("&\"<>", in[x]))
02640          escaped++;
02641    }
02642    len = (size_t) (1 + strlen(in) + colons * 5 + breaks * (40 + strlen(dest) + strlen(objtype)) + escaped * 10); /* foo="bar", "<response type=\"object\" id=\"dest\"", "&amp;" */
02643    out = ast_malloc(len);
02644    if (!out)
02645       return NULL;
02646    tmp = out;
02647    *tmp = '\0';
02648 #endif
02649    /* we want to stop when we find an empty line */
02650    while (in && *in) {
02651       val = strsep(&in, "\r\n"); /* mark start and end of line */
02652       if (in && *in == '\n')     /* remove trailing \n if any */
02653          in++;
02654       ast_trim_blanks(val);
02655       if (0)
02656          ast_verbose("inobj %d in_data %d line <%s>\n", inobj, in_data, val);
02657       if (ast_strlen_zero(val)) {
02658          if (in_data) { /* close data */
02659             ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
02660             in_data = 0;
02661          }
02662          ast_str_append(out, 0, xml ? " /></response>\n" :
02663             "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
02664          inobj = 0;
02665          continue;
02666       }
02667       /* we expect Name: value lines */
02668       if (in_data) {
02669          var = NULL;
02670       } else {
02671          var = strsep(&val, ":");
02672          if (val) {  /* found the field name */
02673             val = ast_skip_blanks(val);
02674             ast_trim_blanks(var);
02675          } else {    /* field name not found, move to opaque mode */
02676             val = var;
02677             var = "Opaque-data";
02678          }
02679       }
02680       if (!inobj) {
02681          if (xml)
02682             ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
02683          else
02684             ast_str_append(out, 0, "<body>\n");
02685          inobj = 1;
02686       }
02687       if (!in_data) {   /* build appropriate line start */
02688          ast_str_append(out, 0, xml ? " " : "<tr><td>");
02689          xml_copy_escape(out, var, xml ? 1 | 2 : 0);
02690          ast_str_append(out, 0, xml ? "='" : "</td><td>");
02691          if (!strcmp(var, "Opaque-data"))
02692             in_data = 1;
02693       }
02694       xml_copy_escape(out, val, 0); /* data field */
02695       if (!in_data)
02696          ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
02697       else
02698          ast_str_append(out, 0, xml ? "\n" : "<br>\n");
02699    }
02700    if (inobj)
02701       ast_str_append(out, 0, xml ? " /></response>\n" :
02702          "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
02703 }


Variable Documentation

struct server_args ami_desc [static]
 

Definition at line 2910 of file manager.c.

Referenced by init_manager().

struct tls_config ami_tls_cfg
 

Definition at line 2909 of file manager.c.

Referenced by init_manager().

struct server_args amis_desc [static]
 

Definition at line 2921 of file manager.c.

Referenced by init_manager().

char* contenttype[] [static]
 

Initial value:

 {
   [FORMAT_RAW] = "plain",
   [FORMAT_HTML] = "html",
   [FORMAT_XML] =  "xml",
}

Definition at line 2489 of file manager.c.

struct ast_http_uri manageruri
 

Definition at line 2883 of file manager.c.

struct ast_http_uri managerxmluri
 

Definition at line 2890 of file manager.c.

struct ast_http_uri rawmanuri
 

Definition at line 2876 of file manager.c.

int registered = 0 [static]
 

Definition at line 2897 of file manager.c.

int webregged = 0 [static]
 

Definition at line 2898 of file manager.c.


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen