Wed Oct 28 11:52:50 2009

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_session
struct  mansession_session::mansession_datastores
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 __fini_actions (void)
static void __fini_manager_hooks (void)
static void __fini_users (void)
static void __init_actions (void)
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_manager_hooks (void)
static void __init_userevent_buf (void)
static void __init_users (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 3446 of file manager.c.

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


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 4025 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, inet_aton(), 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().

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

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

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

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

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

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

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

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

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

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3484 of file manager.c.

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

Referenced by handle_uri(), and static_callback().

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

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

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

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

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

static int compress_char ( char  c  )  [static]

Definition at line 3603 of file manager.c.

Referenced by member_hash_fn(), and variable_count_hash_fn().

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

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

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

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

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

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4340 of file manager.c.

References __init_manager().

Referenced by main().

04341 {
04342    return __init_manager(0);
04343 }

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

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

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

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

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

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

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

References purge_events(), and purge_sessions().

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

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

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

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

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4345 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04346 {
04347    return __init_manager(1);
04348 }

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

Definition at line 3628 of file manager.c.

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

Referenced by xml_translate().

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

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

Definition at line 3616 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

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

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

Definition at line 3542 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

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

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

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


Variable Documentation

Definition at line 4004 of file manager.c.

Referenced by __init_manager().

Definition at line 4003 of file manager.c.

Referenced by __init_manager().

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

Referenced by generic_http_callback().

Definition at line 3973 of file manager.c.

Referenced by __init_manager().

Definition at line 3982 of file manager.c.

Referenced by __init_manager().

Definition at line 3964 of file manager.c.

Referenced by __init_manager().

int registered = 0 [static]

Definition at line 3991 of file manager.c.

Referenced by __init_manager().

int webregged = 0 [static]

Definition at line 3992 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 Wed Oct 28 11:52:51 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6