Thu Apr 8 01:23:08 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 3458 of file manager.c.

03458                    {
03459    FORMAT_RAW,
03460    FORMAT_HTML,
03461    FORMAT_XML,
03462 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 4037 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().

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

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

References AST_LIST_INSERT_HEAD, and mansession::session.

04363 {
04364    AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
04365 
04366    return 0;
04367 }

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

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

04375 {
04376    struct ast_datastore *datastore = NULL;
04377    
04378    if (info == NULL)
04379       return NULL;
04380 
04381    AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
04382       if (datastore->info != info) {
04383          continue;
04384       }
04385 
04386       if (uid == NULL) {
04387          /* matched by type only */
04388          break;
04389       }
04390 
04391       if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
04392          /* Matched by type AND uid */
04393          break;
04394       }
04395    }
04396    AST_LIST_TRAVERSE_SAFE_END;
04397 
04398    return datastore;
04399 }

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

References AST_LIST_REMOVE, and mansession::session.

04370 {
04371    return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
04372 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3496 of file manager.c.

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

Referenced by handle_uri(), and static_callback().

03497 {
03498    int authed;
03499    struct mansession_session *session;
03500 
03501    if (!(session = find_session(ident, 0)))
03502       return 0;
03503 
03504    authed = (session->authenticated != 0);
03505 
03506    ast_mutex_unlock(&session->__lock);
03507 
03508    return authed;
03509 }

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 3511 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.

03512 {
03513    int result = 0;
03514    struct mansession_session *session;
03515 
03516    AST_LIST_LOCK(&sessions);
03517    AST_LIST_TRAVERSE(&sessions, session, list) {
03518       ast_mutex_lock(&session->__lock);
03519       if ((session->managerid == ident) && (session->readperm & perm)) {
03520          result = 1;
03521          ast_mutex_unlock(&session->__lock);
03522          break;
03523       }
03524       ast_mutex_unlock(&session->__lock);
03525    }
03526    AST_LIST_UNLOCK(&sessions);
03527    return result;
03528 }

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 3530 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().

03531 {
03532    int result = 0;
03533    struct mansession_session *session;
03534 
03535    AST_LIST_LOCK(&sessions);
03536    AST_LIST_TRAVERSE(&sessions, session, list) {
03537       ast_mutex_lock(&session->__lock);
03538       if ((session->managerid == ident) && (session->writeperm & perm)) {
03539          result = 1;
03540          ast_mutex_unlock(&session->__lock);
03541          break;
03542       }
03543       ast_mutex_unlock(&session->__lock);
03544    }
03545    AST_LIST_UNLOCK(&sessions);
03546    return result;
03547 }

static int compress_char ( char  c  )  [static]

Definition at line 3615 of file manager.c.

Referenced by variable_count_hash_fn().

03616 {
03617    c &= 0x7f;
03618    if (c < 32)
03619       return 0;
03620    else if (c >= 'a' && c <= 'z')
03621       return c - 64;
03622    else if (c > 'z')
03623       return '_';
03624    else
03625       return c - 32;
03626 }

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 3475 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().

03476 {
03477    struct mansession_session *session;
03478 
03479    if (ident == 0)
03480       return NULL;
03481 
03482    AST_LIST_LOCK(&sessions);
03483    AST_LIST_TRAVERSE(&sessions, session, list) {
03484       ast_mutex_lock(&session->__lock);
03485       if (session->managerid == ident && !session->needdestroy) {
03486          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
03487          break;
03488       }
03489       ast_mutex_unlock(&session->__lock);
03490    }
03491    AST_LIST_UNLOCK(&sessions);
03492 
03493    return session;
03494 }

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 3779 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().

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

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4352 of file manager.c.

References __init_manager().

Referenced by main().

04353 {
04354    return __init_manager(0);
04355 }

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

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

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

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

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

03967 {
03968    return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
03969 }

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

References purge_events(), and purge_sessions().

04010 {
04011    purge_sessions(1);
04012    purge_events();
04013 }

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

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

03972 {
03973    return generic_http_callback(FORMAT_RAW, &ser->remote_address, uri, method, params, status, title, contentlength);
03974 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4357 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04358 {
04359    return __init_manager(1);
04360 }

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

Definition at line 3640 of file manager.c.

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

Referenced by xml_translate().

03641 {
03642    /* Due to the simplicity of struct variable_count, it makes no difference
03643     * if you pass in objects or strings, the same operation applies. This is
03644     * due to the fact that the hash occurs on the first element, which means
03645     * the address of both the struct and the string are exactly the same. */
03646    struct variable_count *vc = obj;
03647    char *str = vstr;
03648    return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
03649 }

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

Definition at line 3628 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

03629 {
03630    const struct variable_count *vc = vvc;
03631    int res = 0, i;
03632    for (i = 0; i < 5; i++) {
03633       if (vc->varname[i] == '\0')
03634          break;
03635       res += compress_char(vc->varname[i]) << (i * 6);
03636    }
03637    return res;
03638 }

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

Definition at line 3554 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

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

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 3679 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().

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


Variable Documentation

Definition at line 4016 of file manager.c.

Referenced by __init_manager().

Definition at line 4015 of file manager.c.

Referenced by __init_manager().

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

Referenced by generic_http_callback().

Definition at line 3985 of file manager.c.

Referenced by __init_manager().

Definition at line 3994 of file manager.c.

Referenced by __init_manager().

Definition at line 3976 of file manager.c.

Referenced by __init_manager().

int registered = 0 [static]

Definition at line 4003 of file manager.c.

Referenced by __init_manager().

int webregged = 0 [static]

Definition at line 4004 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 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1