Tue Mar 2 17:34:01 2010

Asterisk developer's documentation


manager.c File Reference

The Asterisk Management Interface - AMI. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/mman.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.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/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/ast_version.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/version.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"
#include "asterisk/features.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
 helper function for originate More...
struct  mansession
struct  mansession_session
struct  permalias
struct  variable_count

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define GET_HEADER_FIRST_MATCH   0
#define GET_HEADER_LAST_MATCH   1
#define GET_HEADER_SKIP_EMPTY   2
#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"
#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#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->session->last_ev, eq_next))
#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
#define TEST_STRING   "<form action=\"manager\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----&gt;</option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n"

Enumerations

enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}
enum  output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }

Functions

static const char * __astman_get_header (const struct message *m, char *var, int mode)
static int __init_manager (int reload)
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_atxfer (struct mansession *s, const struct message *m)
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_coresettings (struct mansession *s, const struct message *m)
 Show PBX core settings information.
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
static int action_createconfig (struct mansession *s, const struct message *m)
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_getconfigjson (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_listcategories (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_reload (struct mansession *s, const struct message *m)
 Send a reload event.
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 (sessions, mansession_session)
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)
 Unregister a registered manager command.
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)
 list of hooks registered
static AST_RWLIST_HEAD_STATIC (actions, manager_action)
 list of actions registered
static AST_RWLIST_HEAD_STATIC (users, ast_manager_user)
 list of users found in the config file
 AST_THREADSTORAGE (manager_event_buf)
 AST_THREADSTORAGE (userevent_buf)
 AST_THREADSTORAGE (astman_append_buf)
 thread local buffer for astman_append
void astman_append (struct mansession *s, const char *fmt,...)
int astman_datastore_add (struct mansession *s, struct ast_datastore *datastore)
 Add a datastore to a session.
struct ast_datastoreastman_datastore_find (struct mansession *s, const struct ast_datastore_info *info, const char *uid)
 Find a datastore on a session.
int astman_datastore_remove (struct mansession *s, struct ast_datastore *datastore)
 Remove a datastore from a session.
const char * astman_get_header (const struct message *m, char *var)
 Get header from mananger transaction.
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
int astman_is_authed (uint32_t ident)
 Determinie if a manager session ident is authenticated.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
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)
int astman_verify_session_readpermissions (uint32_t ident, int perm)
 Verify a session's read permissions against a permission mask.
int astman_verify_session_writepermissions (uint32_t 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, struct ast_str **res)
 Convert authority code to a list of options.
static int check_blacklist (const char *cmd)
int check_manager_enabled ()
 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 check_manager_session_inuse (const char *name)
int check_webmanager_enabled ()
 Check if AMI/HTTP is enabled.
static int compress_char (char c)
static void destroy_session (struct mansession_session *session)
static int do_message (struct mansession *s)
static void * fast_originate (void *data)
static struct mansession_sessionfind_session (uint32_t ident, int incinuse)
static void free_session (struct mansession_session *session)
static struct ast_strgeneric_http_callback (enum output_format format, struct sockaddr_in *remote_address, const char *uri, enum ast_http_method method, 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)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
int init_manager (void)
 Called by Asterisk initialization.
static void json_escape (char *out, const char *in)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static struct ast_strmanager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength)
static int manager_modulecheck (struct mansession *s, const struct message *m)
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (char *context, char *exten, int state, void *data)
static struct ast_strmxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, 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 ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength)
static void ref_event (struct eventqent *e)
int reload_manager (void)
 Called by Asterisk module functions and the CLI command.
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 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 (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 int allowmultiplelogin = 1
static struct
ast_tcptls_session_args 
ami_desc
struct ast_tls_config ami_tls_cfg
static struct
ast_tcptls_session_args 
amis_desc
static int block_sockets
static struct ast_cli_entry cli_manager []
struct {
   char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static char * contenttype []
static int displayconnects = 1
static int httptimeout = 60
static int manager_debug
static int manager_enabled = 0
struct ast_http_uri manageruri
struct ast_http_uri managerxmluri
static char mandescr_atxfer []
static char mandescr_command []
static char mandescr_coresettings []
static char mandescr_coreshowchannels []
static char mandescr_corestatus []
static char mandescr_createconfig []
static char mandescr_events []
static char mandescr_extensionstate []
static char mandescr_getconfig []
static char mandescr_getconfigjson []
static char mandescr_getvar []
static char mandescr_hangup []
static char mandescr_listcategories []
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_modulecheck []
static char mandescr_moduleload []
static char mandescr_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_reload []
static char mandescr_sendtext []
static char mandescr_setvar []
static char mandescr_status []
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 []
struct ast_http_uri rawmanuri
static int registered = 0
static int timestampevents
static int webmanager_enabled = 0
static int webregged = 0

Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
OpenSSL http://www.openssl.org - for AMI/SSL

At the moment this file contains a number of functions, namely:

manager.conf

Definition in file manager.c.


Define Documentation

#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"

Referenced by handle_showmancmds().

#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"

Referenced by handle_showmanconn().

#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"

Referenced by handle_showmanconn().

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

Referenced by generic_http_callback().

#define TEST_STRING   "<form action=\"manager\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----&gt;</option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n"

Referenced by generic_http_callback().


Enumeration Type Documentation

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 3447 of file manager.c.

03447                    {
03448    FORMAT_RAW,
03449    FORMAT_HTML,
03450    FORMAT_XML,
03451 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 4026 of file manager.c.

References action_atxfer(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_reload(), 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_append_ha(), ast_calloc, ast_category_browse(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_debug, ast_extension_state_add(), ast_free, ast_free_ha(), ast_gethostbyname(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, ast_log(), ast_manager_register2(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_ssl_setup(), ast_strdup, ast_strlen_zero(), ast_tcptls_server_start(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_tls_config::certfile, ast_tls_config::cipher, cli_manager, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, ast_manager_user::displayconnects, ast_tls_config::enabled, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, get_manager_by_name_locked(), get_perm(), ast_manager_user::ha, hp, ast_manager_user::keep, ast_variable::lineno, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_event, manager_modulecheck(), manager_moduleload(), manager_state_cb(), manageruri, managerxmluri, mandescr_atxfer, mandescr_command, mandescr_coresettings, mandescr_coreshowchannels, mandescr_corestatus, mandescr_createconfig, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getconfigjson, mandescr_getvar, mandescr_hangup, mandescr_listcategories, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_modulecheck, mandescr_moduleload, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_reload, mandescr_sendtext, mandescr_setvar, mandescr_status, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, ast_variable::name, ast_variable::next, rawmanuri, ast_manager_user::readperm, registered, ast_manager_user::secret, ast_tcptls_session_args::tls_cfg, ast_manager_user::username, ast_variable::value, var, webregged, ast_manager_user::writeperm, and ast_manager_user::writetimeout.

Referenced by init_manager(), and reload_manager().

04027 {
04028    struct ast_config *ucfg = NULL, *cfg = NULL;
04029    const char *val;
04030    char *cat = NULL;
04031    int newhttptimeout = 60;
04032    int have_sslbindaddr = 0;
04033    struct hostent *hp;
04034    struct ast_hostent ahp;
04035    struct ast_manager_user *user = NULL;
04036    struct ast_variable *var;
04037    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04038 
04039    manager_enabled = 0;
04040 
04041    if (!registered) {
04042       /* Register default actions */
04043       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
04044       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
04045       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
04046       ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
04047       ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
04048       ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
04049       ast_manager_register2("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status", mandescr_status);
04050       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar);
04051       ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar);
04052       ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
04053       ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson);
04054       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
04055       ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig);
04056       ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories);
04057       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
04058       ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer);
04059       ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate);
04060       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
04061       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
04062       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
04063       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
04064       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
04065       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
04066       ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
04067       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
04068       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
04069       ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
04070       ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
04071       ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload);
04072       ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels);
04073       ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload);
04074       ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck);
04075 
04076       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
04077       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
04078       registered = 1;
04079       /* Append placeholder event so master_eventq never runs dry */
04080       append_event("Event: Placeholder\r\n\r\n", 0);
04081    }
04082    if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
04083       return 0;
04084 
04085    displayconnects = 1;
04086    if (!cfg) {
04087       ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf. Asterisk management interface (AMI) disabled.\n");
04088       return 0;
04089    }
04090 
04091    /* default values */
04092    memset(&ami_desc.local_address, 0, sizeof(struct sockaddr_in));
04093    memset(&amis_desc.local_address, 0, sizeof(amis_desc.local_address));
04094    amis_desc.local_address.sin_port = htons(5039);
04095    ami_desc.local_address.sin_port = htons(DEFAULT_MANAGER_PORT);
04096 
04097    ami_tls_cfg.enabled = 0;
04098    if (ami_tls_cfg.certfile)
04099       ast_free(ami_tls_cfg.certfile);
04100    ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
04101    if (ami_tls_cfg.cipher)
04102       ast_free(ami_tls_cfg.cipher);
04103    ami_tls_cfg.cipher = ast_strdup("");
04104 
04105    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
04106       val = var->value;
04107       if (!strcasecmp(var->name, "sslenable"))
04108          ami_tls_cfg.enabled = ast_true(val);
04109       else if (!strcasecmp(var->name, "sslbindport"))
04110          amis_desc.local_address.sin_port = htons(atoi(val));
04111       else if (!strcasecmp(var->name, "sslbindaddr")) {
04112          if ((hp = ast_gethostbyname(val, &ahp))) {
04113             memcpy(&amis_desc.local_address.sin_addr, hp->h_addr, sizeof(amis_desc.local_address.sin_addr));
04114             have_sslbindaddr = 1;
04115          } else {
04116             ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
04117          }
04118       } else if (!strcasecmp(var->name, "sslcert")) {
04119          ast_free(ami_tls_cfg.certfile);
04120          ami_tls_cfg.certfile = ast_strdup(val);
04121       } else if (!strcasecmp(var->name, "sslcipher")) {
04122          ast_free(ami_tls_cfg.cipher);
04123          ami_tls_cfg.cipher = ast_strdup(val);
04124       } else if (!strcasecmp(var->name, "enabled")) {
04125          manager_enabled = ast_true(val);
04126       } else if (!strcasecmp(var->name, "block-sockets")) {
04127          block_sockets = ast_true(val);
04128       } else if (!strcasecmp(var->name, "webenabled")) {
04129          webmanager_enabled = ast_true(val);
04130       } else if (!strcasecmp(var->name, "port")) {
04131          ami_desc.local_address.sin_port = htons(atoi(val));
04132       } else if (!strcasecmp(var->name, "bindaddr")) {
04133          if (!inet_aton(val, &ami_desc.local_address.sin_addr)) {
04134             ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
04135             memset(&ami_desc.local_address.sin_addr, 0, sizeof(ami_desc.local_address.sin_addr));
04136          }
04137       } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 
04138          allowmultiplelogin = ast_true(val);
04139       } else if (!strcasecmp(var->name, "displayconnects")) {
04140          displayconnects = ast_true(val);
04141       } else if (!strcasecmp(var->name, "timestampevents")) {
04142          timestampevents = ast_true(val);
04143       } else if (!strcasecmp(var->name, "debug")) {
04144          manager_debug = ast_true(val);
04145       } else if (!strcasecmp(var->name, "httptimeout")) {
04146          newhttptimeout = atoi(val);
04147       } else {
04148          ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
04149             var->name, val);
04150       }  
04151    }
04152 
04153    if (manager_enabled)
04154       ami_desc.local_address.sin_family = AF_INET;
04155    if (!have_sslbindaddr)
04156       amis_desc.local_address.sin_addr = ami_desc.local_address.sin_addr;
04157    if (ami_tls_cfg.enabled)
04158       amis_desc.local_address.sin_family = AF_INET;
04159 
04160    
04161    AST_RWLIST_WRLOCK(&users);
04162 
04163    /* First, get users from users.conf */
04164    ucfg = ast_config_load2("users.conf", "manager", config_flags);
04165    if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED)) {
04166       const char *hasmanager;
04167       int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
04168 
04169       while ((cat = ast_category_browse(ucfg, cat))) {
04170          if (!strcasecmp(cat, "general"))
04171             continue;
04172          
04173          hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
04174          if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
04175             const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
04176             const char *user_read = ast_variable_retrieve(ucfg, cat, "read");
04177             const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
04178             const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
04179             const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
04180             
04181             /* Look for an existing entry,
04182              * if none found - create one and add it to the list
04183              */
04184             if (!(user = get_manager_by_name_locked(cat))) {
04185                if (!(user = ast_calloc(1, sizeof(*user))))
04186                   break;
04187 
04188                /* Copy name over */
04189                ast_copy_string(user->username, cat, sizeof(user->username));
04190                /* Insert into list */
04191                AST_LIST_INSERT_TAIL(&users, user, list);
04192                user->ha = NULL;
04193                user->keep = 1;
04194                user->readperm = -1;
04195                user->writeperm = -1;
04196                /* Default displayconnect from [general] */
04197                user->displayconnects = displayconnects;
04198                user->writetimeout = 100;
04199             }
04200 
04201             if (!user_secret)
04202                user_secret = ast_variable_retrieve(ucfg, "general", "secret");
04203             if (!user_read)
04204                user_read = ast_variable_retrieve(ucfg, "general", "read");
04205             if (!user_write)
04206                user_write = ast_variable_retrieve(ucfg, "general", "write");
04207             if (!user_displayconnects)
04208                user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
04209             if (!user_writetimeout)
04210                user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
04211 
04212             if (!ast_strlen_zero(user_secret)) {
04213                if (user->secret)
04214                   ast_free(user->secret);
04215                user->secret = ast_strdup(user_secret);
04216             }
04217 
04218             if (user_read)
04219                user->readperm = get_perm(user_read);
04220             if (user_write)
04221                user->writeperm = get_perm(user_write);
04222             if (user_displayconnects)
04223                user->displayconnects = ast_true(user_displayconnects);
04224 
04225             if (user_writetimeout) {
04226                int value = atoi(user_writetimeout);
04227                if (value < 100)
04228                   ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
04229                else
04230                   user->writetimeout = value;
04231             }
04232          }
04233       }
04234       ast_config_destroy(ucfg);
04235    }
04236 
04237    /* cat is NULL here in any case */
04238 
04239    while ((cat = ast_category_browse(cfg, cat))) {
04240       struct ast_ha *oldha;
04241 
04242       if (!strcasecmp(cat, "general"))
04243          continue;
04244 
04245       /* Look for an existing entry, if none found - create one and add it to the list */
04246       if (!(user = get_manager_by_name_locked(cat))) {
04247          if (!(user = ast_calloc(1, sizeof(*user))))
04248             break;
04249          /* Copy name over */
04250          ast_copy_string(user->username, cat, sizeof(user->username));
04251 
04252          user->ha = NULL;
04253          user->readperm = 0;
04254          user->writeperm = 0;
04255          /* Default displayconnect from [general] */
04256          user->displayconnects = displayconnects;
04257          user->writetimeout = 100;
04258 
04259          /* Insert into list */
04260          AST_RWLIST_INSERT_TAIL(&users, user, list);
04261       }
04262 
04263       /* Make sure we keep this user and don't destroy it during cleanup */
04264       user->keep = 1;
04265       oldha = user->ha;
04266       user->ha = NULL;
04267 
04268       var = ast_variable_browse(cfg, cat);
04269       for (; var; var = var->next) {
04270          if (!strcasecmp(var->name, "secret")) {
04271             if (user->secret)
04272                ast_free(user->secret);
04273             user->secret = ast_strdup(var->value);
04274          } else if (!strcasecmp(var->name, "deny") ||
04275                    !strcasecmp(var->name, "permit")) {
04276             user->ha = ast_append_ha(var->name, var->value, user->ha, NULL);
04277          }  else if (!strcasecmp(var->name, "read") ) {
04278             user->readperm = get_perm(var->value);
04279          }  else if (!strcasecmp(var->name, "write") ) {
04280             user->writeperm = get_perm(var->value);
04281          }  else if (!strcasecmp(var->name, "displayconnects") ) {
04282             user->displayconnects = ast_true(var->value);
04283          } else if (!strcasecmp(var->name, "writetimeout")) {
04284             int value = atoi(var->value);
04285             if (value < 100)
04286                ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
04287             else
04288                user->writetimeout = value;
04289          } else
04290             ast_debug(1, "%s is an unknown option.\n", var->name);
04291       }
04292       ast_free_ha(oldha);
04293    }
04294    ast_config_destroy(cfg);
04295 
04296    /* Perform cleanup - essentially prune out old users that no longer exist */
04297    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
04298       if (user->keep) { /* valid record. clear flag for the next round */
04299          user->keep = 0;
04300          continue;
04301       }
04302       /* We do not need to keep this user so take them out of the list */
04303       AST_RWLIST_REMOVE_CURRENT(list);
04304       /* Free their memory now */
04305       if (user->secret)
04306          ast_free(user->secret);
04307       ast_free_ha(user->ha);
04308       ast_free(user);
04309    }
04310    AST_RWLIST_TRAVERSE_SAFE_END;
04311 
04312    AST_RWLIST_UNLOCK(&users);
04313 
04314    if (webmanager_enabled && manager_enabled) {
04315       if (!webregged) {
04316          ast_http_uri_link(&rawmanuri);
04317          ast_http_uri_link(&manageruri);
04318          ast_http_uri_link(&managerxmluri);
04319          webregged = 1;
04320       }
04321    } else {
04322       if (webregged) {
04323          ast_http_uri_unlink(&rawmanuri);
04324          ast_http_uri_unlink(&manageruri);
04325          ast_http_uri_unlink(&managerxmluri);
04326          webregged = 0;
04327       }
04328    }
04329 
04330    if (newhttptimeout > 0)
04331       httptimeout = newhttptimeout;
04332 
04333    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
04334 
04335    ast_tcptls_server_start(&ami_desc);
04336    if (ast_ssl_setup(amis_desc.tls_cfg))
04337       ast_tcptls_server_start(&amis_desc);
04338    return 0;
04339 }

int astman_datastore_add ( struct mansession s,
struct ast_datastore datastore 
)

Add a datastore to a session.

Return values:
0 success
non-zero failure
Since:
1.6.1

Definition at line 4351 of file manager.c.

References AST_LIST_INSERT_HEAD, and mansession::session.

04352 {
04353    AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
04354 
04355    return 0;
04356 }

struct ast_datastore* astman_datastore_find ( struct mansession s,
const struct ast_datastore_info info,
const char *  uid 
) [read]

Find a datastore on a session.

Return values:
pointer to the datastore if found
NULL if not found
Since:
1.6.1

Definition at line 4363 of file manager.c.

References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_datastore::info, mansession::session, and ast_datastore::uid.

04364 {
04365    struct ast_datastore *datastore = NULL;
04366    
04367    if (info == NULL)
04368       return NULL;
04369 
04370    AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
04371       if (datastore->info != info) {
04372          continue;
04373       }
04374 
04375       if (uid == NULL) {
04376          /* matched by type only */
04377          break;
04378       }
04379 
04380       if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
04381          /* Matched by type AND uid */
04382          break;
04383       }
04384    }
04385    AST_LIST_TRAVERSE_SAFE_END;
04386 
04387    return datastore;
04388 }

int astman_datastore_remove ( struct mansession s,
struct ast_datastore datastore 
)

Remove a datastore from a session.

Return values:
0 success
non-zero failure
Since:
1.6.1

Definition at line 4358 of file manager.c.

References AST_LIST_REMOVE, and mansession::session.

04359 {
04360    return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
04361 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3485 of file manager.c.

References mansession_session::__lock, ast_mutex_unlock(), mansession_session::authenticated, and find_session().

Referenced by handle_uri(), and static_callback().

03486 {
03487    int authed;
03488    struct mansession_session *session;
03489 
03490    if (!(session = find_session(ident, 0)))
03491       return 0;
03492 
03493    authed = (session->authenticated != 0);
03494 
03495    ast_mutex_unlock(&session->__lock);
03496 
03497    return authed;
03498 }

int astman_verify_session_readpermissions ( uint32_t  ident,
int  perm 
)

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

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

Definition at line 3500 of file manager.c.

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

03501 {
03502    int result = 0;
03503    struct mansession_session *session;
03504 
03505    AST_LIST_LOCK(&sessions);
03506    AST_LIST_TRAVERSE(&sessions, session, list) {
03507       ast_mutex_lock(&session->__lock);
03508       if ((session->managerid == ident) && (session->readperm & perm)) {
03509          result = 1;
03510          ast_mutex_unlock(&session->__lock);
03511          break;
03512       }
03513       ast_mutex_unlock(&session->__lock);
03514    }
03515    AST_LIST_UNLOCK(&sessions);
03516    return result;
03517 }

int astman_verify_session_writepermissions ( uint32_t  ident,
int  perm 
)

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

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

Definition at line 3519 of file manager.c.

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

Referenced by http_post_callback().

03520 {
03521    int result = 0;
03522    struct mansession_session *session;
03523 
03524    AST_LIST_LOCK(&sessions);
03525    AST_LIST_TRAVERSE(&sessions, session, list) {
03526       ast_mutex_lock(&session->__lock);
03527       if ((session->managerid == ident) && (session->writeperm & perm)) {
03528          result = 1;
03529          ast_mutex_unlock(&session->__lock);
03530          break;
03531       }
03532       ast_mutex_unlock(&session->__lock);
03533    }
03534    AST_LIST_UNLOCK(&sessions);
03535    return result;
03536 }

static int compress_char ( char  c  )  [static]

Definition at line 3604 of file manager.c.

Referenced by variable_count_hash_fn().

03605 {
03606    c &= 0x7f;
03607    if (c < 32)
03608       return 0;
03609    else if (c >= 'a' && c <= 'z')
03610       return c - 64;
03611    else if (c > 'z')
03612       return '_';
03613    else
03614       return c - 32;
03615 }

static struct mansession_session* find_session ( uint32_t  ident,
int  incinuse 
) [static, read]

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 3464 of file manager.c.

References mansession_session::__lock, ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::inuse, mansession_session::managerid, and mansession_session::needdestroy.

Referenced by astman_is_authed(), and generic_http_callback().

03465 {
03466    struct mansession_session *session;
03467 
03468    if (ident == 0)
03469       return NULL;
03470 
03471    AST_LIST_LOCK(&sessions);
03472    AST_LIST_TRAVERSE(&sessions, session, list) {
03473       ast_mutex_lock(&session->__lock);
03474       if (session->managerid == ident && !session->needdestroy) {
03475          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
03476          break;
03477       }
03478       ast_mutex_unlock(&session->__lock);
03479    }
03480    AST_LIST_UNLOCK(&sessions);
03481 
03482    return session;
03483 }

static struct ast_str* generic_http_callback ( enum output_format  format,
struct sockaddr_in *  remote_address,
const char *  uri,
enum ast_http_method  method,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

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 3768 of file manager.c.

References mansession_session::__lock, ast_atomic_fetchadd_int(), ast_calloc, ast_debug, ast_http_error(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, 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_random(), ast_str_append(), ast_str_create(), ast_verb, mansession_session::authenticated, buf, contenttype, destroy_session(), mansession::f, mansession::fd, mansession_session::fd, find_session(), FORMAT_HTML, FORMAT_XML, grab_last(), message::hdrcount, message::headers, mansession_session::inuse, LOG_EVENT, LOG_WARNING, manager_displayconnects(), mansession_session::managerid, ast_variable::name, mansession_session::needdestroy, ast_variable::next, process_message(), ROW_FMT, s, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, mansession_session::sin, TEST_STRING, mansession_session::username, ast_variable::value, mansession_session::waiting_thread, and xml_translate().

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

03772 {
03773    struct mansession s = {.session = NULL, };
03774    struct mansession_session *session = NULL;
03775    uint32_t ident = 0;
03776    int blastaway = 0;
03777    struct ast_variable *v;
03778    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
03779    struct ast_str *out = NULL;
03780    struct message m = { 0 };
03781    unsigned int x;
03782    size_t hdrlen;
03783 
03784    for (v = params; v; v = v->next) {
03785       if (!strcasecmp(v->name, "mansession_id")) {
03786          sscanf(v->value, "%30x", &ident);
03787          break;
03788       }
03789    }
03790 
03791    if (!(session = find_session(ident, 1))) {
03792       /* Create new session.
03793        * While it is not in the list we don't need any locking
03794        */
03795       if (!(session = ast_calloc(1, sizeof(*session)))) {
03796          *status = 500;
03797          goto generic_callback_out;
03798       }
03799       session->sin = *remote_address;
03800       session->fd = -1;
03801       session->waiting_thread = AST_PTHREADT_NULL;
03802       session->send_events = 0;
03803       ast_mutex_init(&session->__lock);
03804       ast_mutex_lock(&session->__lock);
03805       session->inuse = 1;
03806       /*!\note There is approximately a 1 in 1.8E19 chance that the following
03807        * calculation will produce 0, which is an invalid ID, but due to the
03808        * properties of the rand() function (and the constantcy of s), that
03809        * won't happen twice in a row.
03810        */
03811       while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
03812       session->last_ev = grab_last();
03813       AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
03814       AST_LIST_LOCK(&sessions);
03815       AST_LIST_INSERT_HEAD(&sessions, session, list);
03816       ast_atomic_fetchadd_int(&num_sessions, 1);
03817       AST_LIST_UNLOCK(&sessions);
03818    }
03819 
03820    s.session = session;
03821 
03822    ast_mutex_unlock(&session->__lock);
03823 
03824    if (!(out = ast_str_create(1024))) {
03825       *status = 500;
03826       goto generic_callback_out;
03827    }
03828 
03829    s.fd = mkstemp(template);  /* create a temporary file for command output */
03830    unlink(template);
03831    s.f = fdopen(s.fd, "w+");
03832 
03833    for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
03834       hdrlen = strlen(v->name) + strlen(v->value) + 3;
03835       m.headers[m.hdrcount] = alloca(hdrlen);
03836       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
03837       ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]);
03838       m.hdrcount = x + 1;
03839    }
03840 
03841    if (process_message(&s, &m)) {
03842       if (session->authenticated) {
03843          if (manager_displayconnects(session)) {
03844             ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03845          }
03846          ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03847       } else {
03848          if (displayconnects) {
03849             ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
03850          }
03851          ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
03852       }
03853       session->needdestroy = 1;
03854    }
03855 
03856    ast_str_append(&out, 0,
03857              "Content-type: text/%s\r\n"
03858              "Cache-Control: no-cache;\r\n"
03859              "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n"
03860              "\r\n",
03861          contenttype[format],
03862          session->managerid, httptimeout);
03863 
03864    if (format == FORMAT_XML) {
03865       ast_str_append(&out, 0, "<ajax-response>\n");
03866    } else if (format == FORMAT_HTML) {
03867       /*
03868        * When handling AMI-over-HTTP in HTML format, we provide a simple form for
03869        * debugging purposes. This HTML code should not be here, we
03870        * should read from some config file...
03871        */
03872 
03873 #define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
03874 #define TEST_STRING \
03875    "<form action=\"manager\">\n\
03876    Action: <select name=\"action\">\n\
03877       <option value=\"\">-----&gt;</option>\n\
03878       <option value=\"login\">login</option>\n\
03879       <option value=\"command\">Command</option>\n\
03880       <option value=\"waitevent\">waitevent</option>\n\
03881       <option value=\"listcommands\">listcommands</option>\n\
03882    </select>\n\
03883    or <input name=\"action\"><br/>\n\
03884    CLI Command <input name=\"command\"><br>\n\
03885    user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\
03886    <input type=\"submit\">\n</form>\n"
03887 
03888       ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
03889       ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
03890       ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
03891       ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
03892    }
03893 
03894    if (s.f != NULL) {   /* have temporary output */
03895       char *buf;
03896       size_t l;
03897       
03898       /* Ensure buffer is NULL-terminated */
03899       fprintf(s.f, "%c", 0);
03900 
03901       if ((l = ftell(s.f))) {
03902          if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
03903             ast_log(LOG_WARNING, "mmap failed.  Manager output was not processed\n");
03904          } else {
03905             if (format == FORMAT_XML || format == FORMAT_HTML)
03906                xml_translate(&out, buf, params, format);
03907             else
03908                ast_str_append(&out, 0, "%s", buf);
03909             munmap(buf, l);
03910          }
03911       } else if (format == FORMAT_XML || format == FORMAT_HTML) {
03912          xml_translate(&out, "", params, format);
03913       }
03914       fclose(s.f);
03915       s.f = NULL;
03916       s.fd = -1;
03917    }
03918 
03919    if (format == FORMAT_XML) {
03920       ast_str_append(&out, 0, "</ajax-response>\n");
03921    } else if (format == FORMAT_HTML)
03922       ast_str_append(&out, 0, "</table></body>\r\n");
03923 
03924    ast_mutex_lock(&session->__lock);
03925    /* Reset HTTP timeout.  If we're not authenticated, keep it extremely short */
03926    session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
03927 
03928    if (session->needdestroy) {
03929       if (session->inuse == 1) {
03930          ast_debug(1, "Need destroy, doing it now!\n");
03931          blastaway = 1;
03932       } else {
03933          ast_debug(1, "Need destroy, but can't do it yet!\n");
03934          if (session->waiting_thread != AST_PTHREADT_NULL)
03935             pthread_kill(session->waiting_thread, SIGURG);
03936          session->inuse--;
03937       }
03938    } else
03939       session->inuse--;
03940    ast_mutex_unlock(&session->__lock);
03941 
03942    if (blastaway)
03943       destroy_session(session);
03944 generic_callback_out:
03945    if (*status != 200)
03946       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
03947    return out;
03948 }

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4341 of file manager.c.

References __init_manager().

Referenced by main().

04342 {
04343    return __init_manager(0);
04344 }

static struct ast_str* manager_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable params,
struct ast_variable headers,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3950 of file manager.c.

References FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

03951 {
03952    return generic_http_callback(FORMAT_HTML, &ser->remote_address, uri, method, params, status, title, contentlength);
03953 }

static struct ast_str* mxml_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable params,
struct ast_variable headers,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3955 of file manager.c.

References FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

03956 {
03957    return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
03958 }

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 3998 of file manager.c.

References purge_events(), and purge_sessions().

03999 {
04000    purge_sessions(1);
04001    purge_events();
04002 }

static struct ast_str* rawman_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable params,
struct ast_variable headers,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3960 of file manager.c.

References FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

03961 {
03962    return generic_http_callback(FORMAT_RAW, &ser->remote_address, uri, method, params, status, title, contentlength);
03963 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4346 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04347 {
04348    return __init_manager(1);
04349 }

static int variable_count_cmp_fn ( void *  obj,
void *  vstr,
int  flags 
) [static]

Definition at line 3629 of file manager.c.

References CMP_MATCH, CMP_STOP, str, and variable_count::varname.

Referenced by xml_translate().

03630 {
03631    /* Due to the simplicity of struct variable_count, it makes no difference
03632     * if you pass in objects or strings, the same operation applies. This is
03633     * due to the fact that the hash occurs on the first element, which means
03634     * the address of both the struct and the string are exactly the same. */
03635    struct variable_count *vc = obj;
03636    char *str = vstr;
03637    return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
03638 }

static int variable_count_hash_fn ( const void *  vvc,
const int  flags 
) [static]

Definition at line 3617 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

03618 {
03619    const struct variable_count *vc = vvc;
03620    int res = 0, i;
03621    for (i = 0; i < 5; i++) {
03622       if (vc->varname[i] == '\0')
03623          break;
03624       res += compress_char(vc->varname[i]) << (i * 6);
03625    }
03626    return res;
03627 }

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

Definition at line 3543 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

03544 {
03545    /* store in a local buffer to avoid calling ast_str_append too often */
03546    char buf[256];
03547    char *dst = buf;
03548    int space = sizeof(buf);
03549    /* repeat until done and nothing to flush */
03550    for ( ; *src || dst != buf ; src++) {
03551       if (*src == '\0' || space < 10) {   /* flush */
03552          *dst++ = '\0';
03553          ast_str_append(out, 0, "%s", buf);
03554          dst = buf;
03555          space = sizeof(buf);
03556          if (*src == '\0')
03557             break;
03558       }
03559          
03560       if ( (mode & 2) && !isalnum(*src)) {
03561          *dst++ = '_';
03562          space--;
03563          continue;
03564       }
03565       switch (*src) {
03566       case '<':
03567          strcpy(dst, "&lt;");
03568          dst += 4;
03569          space -= 4;
03570          break;
03571       case '>':
03572          strcpy(dst, "&gt;");
03573          dst += 4;
03574          space -= 4;
03575          break;
03576       case '\"':
03577          strcpy(dst, "&quot;");
03578          dst += 6;
03579          space -= 6;
03580          break;
03581       case '\'':
03582          strcpy(dst, "&apos;");
03583          dst += 6;
03584          space -= 6;
03585          break;
03586       case '&':
03587          strcpy(dst, "&amp;");
03588          dst += 5;
03589          space -= 5;
03590          break;
03591 
03592       default:
03593          *dst++ = mode ? tolower(*src) : *src;
03594          space--;
03595       }
03596    }
03597 }

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 3668 of file manager.c.

References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_skip_blanks(), ast_str_append(), ast_strlen_zero(), ast_trim_blanks(), variable_count::count, FORMAT_XML, ast_variable::name, ast_variable::next, strsep(), ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().

Referenced by generic_http_callback().

03669 {
03670    struct ast_variable *v;
03671    const char *dest = NULL;
03672    char *var, *val;
03673    const char *objtype = NULL;
03674    int in_data = 0;  /* parsing data */
03675    int inobj = 0;
03676    int xml = (format == FORMAT_XML);
03677    struct variable_count *vc = NULL;
03678    struct ao2_container *vco = NULL;
03679 
03680    for (v = vars; v; v = v->next) {
03681       if (!dest && !strcasecmp(v->name, "ajaxdest"))
03682          dest = v->value;
03683       else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
03684          objtype = v->value;
03685    }
03686    if (!dest)
03687       dest = "unknown";
03688    if (!objtype)
03689       objtype = "generic";
03690 
03691    /* we want to stop when we find an empty line */
03692    while (in && *in) {
03693       val = strsep(&in, "\r\n"); /* mark start and end of line */
03694       if (in && *in == '\n')     /* remove trailing \n if any */
03695          in++;
03696       ast_trim_blanks(val);
03697       ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
03698       if (ast_strlen_zero(val)) {
03699          if (in_data) { /* close data */
03700             ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03701             in_data = 0;
03702          }
03703          if (inobj) {
03704             ast_str_append(out, 0, xml ? " /></response>\n" :
03705                "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03706             inobj = 0;
03707             ao2_ref(vco, -1);
03708             vco = NULL;
03709          }
03710          continue;
03711       }
03712 
03713       /* we expect Name: value lines */
03714       if (in_data) {
03715          var = NULL;
03716       } else {
03717          var = strsep(&val, ":");
03718          if (val) {  /* found the field name */
03719             val = ast_skip_blanks(val);
03720             ast_trim_blanks(var);
03721          } else {    /* field name not found, move to opaque mode */
03722             val = var;
03723             var = "Opaque-data";
03724          }
03725       }
03726 
03727       if (!inobj) {
03728          if (xml)
03729             ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
03730          else
03731             ast_str_append(out, 0, "<body>\n");
03732          vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
03733          inobj = 1;
03734       }
03735 
03736       if (!in_data) {   /* build appropriate line start */
03737          ast_str_append(out, 0, xml ? " " : "<tr><td>");
03738          if ((vc = ao2_find(vco, var, 0)))
03739             vc->count++;
03740          else {
03741             /* Create a new entry for this one */
03742             vc = ao2_alloc(sizeof(*vc), NULL);
03743             vc->varname = var;
03744             vc->count = 1;
03745             ao2_link(vco, vc);
03746          }
03747          xml_copy_escape(out, var, xml ? 1 | 2 : 0);
03748          if (vc->count > 1)
03749             ast_str_append(out, 0, "-%d", vc->count);
03750          ao2_ref(vc, -1);
03751          ast_str_append(out, 0, xml ? "='" : "</td><td>");
03752          if (!strcmp(var, "Opaque-data"))
03753             in_data = 1;
03754       }
03755       xml_copy_escape(out, val, 0); /* data field */
03756       if (!in_data)
03757          ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03758       else
03759          ast_str_append(out, 0, xml ? "\n" : "<br>\n");
03760    }
03761    if (inobj) {
03762       ast_str_append(out, 0, xml ? " /></response>\n" :
03763          "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03764       ao2_ref(vco, -1);
03765    }
03766 }


Variable Documentation

Definition at line 4005 of file manager.c.

Referenced by __init_manager().

Definition at line 4004 of file manager.c.

Referenced by __init_manager().

Definition at line 4016 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 3453 of file manager.c.

Referenced by generic_http_callback().

Definition at line 3974 of file manager.c.

Referenced by __init_manager().

Definition at line 3983 of file manager.c.

Referenced by __init_manager().

Definition at line 3965 of file manager.c.

Referenced by __init_manager().

int registered = 0 [static]

Definition at line 3992 of file manager.c.

Referenced by __init_manager().

int webregged = 0 [static]

Definition at line 3993 of file manager.c.

Referenced by __init_manager().

char* words[AST_MAX_CMD_LEN]

Definition at line 145 of file manager.c.

Referenced by check_blacklist().


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1