Fri Nov 12 12:05:24 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  actions
 list of actions registered More...
struct  all_events
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  manager_hooks
 list of hooks registered More...
struct  mansession
struct  mansession_datastores
struct  mansession_session
struct  permalias
struct  sessions
struct  users
 list of users found in the config file More...
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 void __init_astman_append_buf (void)
 thread local buffer for astman_append
static int __init_manager (int reload)
static void __init_manager_event_buf (void)
static void __init_userevent_buf (void)
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)
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.
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 struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
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
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
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 struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
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 3483 of file manager.c.

03483                    {
03484    FORMAT_RAW,
03485    FORMAT_HTML,
03486    FORMAT_XML,
03487 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 4061 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(), ARRAY_LEN, 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_FILEINVALID, 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().

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

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

References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.

04387 {
04388    AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
04389 
04390    return 0;
04391 }

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

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

04399 {
04400    struct ast_datastore *datastore = NULL;
04401    
04402    if (info == NULL)
04403       return NULL;
04404 
04405    AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
04406       if (datastore->info != info) {
04407          continue;
04408       }
04409 
04410       if (uid == NULL) {
04411          /* matched by type only */
04412          break;
04413       }
04414 
04415       if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
04416          /* Matched by type AND uid */
04417          break;
04418       }
04419    }
04420    AST_LIST_TRAVERSE_SAFE_END;
04421 
04422    return datastore;
04423 }

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

References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.

04394 {
04395    return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
04396 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3521 of file manager.c.

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

Referenced by handle_uri(), and static_callback().

03522 {
03523    int authed;
03524    struct mansession_session *session;
03525 
03526    if (!(session = find_session(ident, 0)))
03527       return 0;
03528 
03529    authed = (session->authenticated != 0);
03530 
03531    ast_mutex_unlock(&session->__lock);
03532 
03533    return authed;
03534 }

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

03537 {
03538    int result = 0;
03539    struct mansession_session *session;
03540 
03541    AST_LIST_LOCK(&sessions);
03542    AST_LIST_TRAVERSE(&sessions, session, list) {
03543       ast_mutex_lock(&session->__lock);
03544       if ((session->managerid == ident) && (session->readperm & perm)) {
03545          result = 1;
03546          ast_mutex_unlock(&session->__lock);
03547          break;
03548       }
03549       ast_mutex_unlock(&session->__lock);
03550    }
03551    AST_LIST_UNLOCK(&sessions);
03552    return result;
03553 }

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

03556 {
03557    int result = 0;
03558    struct mansession_session *session;
03559 
03560    AST_LIST_LOCK(&sessions);
03561    AST_LIST_TRAVERSE(&sessions, session, list) {
03562       ast_mutex_lock(&session->__lock);
03563       if ((session->managerid == ident) && (session->writeperm & perm)) {
03564          result = 1;
03565          ast_mutex_unlock(&session->__lock);
03566          break;
03567       }
03568       ast_mutex_unlock(&session->__lock);
03569    }
03570    AST_LIST_UNLOCK(&sessions);
03571    return result;
03572 }

static int compress_char ( char  c  )  [static]

Definition at line 3640 of file manager.c.

Referenced by variable_count_hash_fn().

03641 {
03642    c &= 0x7f;
03643    if (c < 32)
03644       return 0;
03645    else if (c >= 'a' && c <= 'z')
03646       return c - 64;
03647    else if (c > 'z')
03648       return '_';
03649    else
03650       return c - 32;
03651 }

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

03501 {
03502    struct mansession_session *session;
03503 
03504    if (ident == 0)
03505       return NULL;
03506 
03507    AST_LIST_LOCK(&sessions);
03508    AST_LIST_TRAVERSE(&sessions, session, list) {
03509       ast_mutex_lock(&session->__lock);
03510       if (session->managerid == ident && !session->needdestroy) {
03511          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
03512          break;
03513       }
03514       ast_mutex_unlock(&session->__lock);
03515    }
03516    AST_LIST_UNLOCK(&sessions);
03517 
03518    return session;
03519 }

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 3804 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, 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().

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

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4376 of file manager.c.

References __init_manager().

Referenced by main().

04377 {
04378    return __init_manager(0);
04379 }

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

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

03986 {
03987    return generic_http_callback(FORMAT_HTML, &ser->remote_address, uri, method, params, status, title, contentlength);
03988 }

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

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

03991 {
03992    return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
03993 }

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

References purge_events(), and purge_sessions().

04034 {
04035    purge_sessions(1);
04036    purge_events();
04037 }

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

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

03996 {
03997    return generic_http_callback(FORMAT_RAW, &ser->remote_address, uri, method, params, status, title, contentlength);
03998 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4381 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04382 {
04383    return __init_manager(1);
04384 }

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

Definition at line 3665 of file manager.c.

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

Referenced by xml_translate().

03666 {
03667    /* Due to the simplicity of struct variable_count, it makes no difference
03668     * if you pass in objects or strings, the same operation applies. This is
03669     * due to the fact that the hash occurs on the first element, which means
03670     * the address of both the struct and the string are exactly the same. */
03671    struct variable_count *vc = obj;
03672    char *str = vstr;
03673    return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
03674 }

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

Definition at line 3653 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

03654 {
03655    const struct variable_count *vc = vvc;
03656    int res = 0, i;
03657    for (i = 0; i < 5; i++) {
03658       if (vc->varname[i] == '\0')
03659          break;
03660       res += compress_char(vc->varname[i]) << (i * 6);
03661    }
03662    return res;
03663 }

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

Definition at line 3579 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

03580 {
03581    /* store in a local buffer to avoid calling ast_str_append too often */
03582    char buf[256];
03583    char *dst = buf;
03584    int space = sizeof(buf);
03585    /* repeat until done and nothing to flush */
03586    for ( ; *src || dst != buf ; src++) {
03587       if (*src == '\0' || space < 10) {   /* flush */
03588          *dst++ = '\0';
03589          ast_str_append(out, 0, "%s", buf);
03590          dst = buf;
03591          space = sizeof(buf);
03592          if (*src == '\0')
03593             break;
03594       }
03595          
03596       if ( (mode & 2) && !isalnum(*src)) {
03597          *dst++ = '_';
03598          space--;
03599          continue;
03600       }
03601       switch (*src) {
03602       case '<':
03603          strcpy(dst, "&lt;");
03604          dst += 4;
03605          space -= 4;
03606          break;
03607       case '>':
03608          strcpy(dst, "&gt;");
03609          dst += 4;
03610          space -= 4;
03611          break;
03612       case '\"':
03613          strcpy(dst, "&quot;");
03614          dst += 6;
03615          space -= 6;
03616          break;
03617       case '\'':
03618          strcpy(dst, "&apos;");
03619          dst += 6;
03620          space -= 6;
03621          break;
03622       case '&':
03623          strcpy(dst, "&amp;");
03624          dst += 5;
03625          space -= 5;
03626          break;
03627 
03628       default:
03629          *dst++ = mode ? tolower(*src) : *src;
03630          space--;
03631       }
03632    }
03633 }

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 3704 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, ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().

Referenced by generic_http_callback().

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


Variable Documentation

Definition at line 4040 of file manager.c.

Referenced by __init_manager().

Definition at line 4039 of file manager.c.

Referenced by __init_manager().

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

Referenced by generic_http_callback().

Definition at line 4009 of file manager.c.

Referenced by __init_manager().

Definition at line 4018 of file manager.c.

Referenced by __init_manager().

Definition at line 4000 of file manager.c.

Referenced by __init_manager().

int registered = 0 [static]

Definition at line 4027 of file manager.c.

Referenced by __init_manager().

int webregged = 0 [static]

Definition at line 4028 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 by  doxygen 1.6.2