Fri Jun 19 12:10:41 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"

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 __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 manager command with the manager interface.
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.
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.
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 ()
 Check if AMI is enabled.
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
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 , }
ast_http_uri manageruri
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 []
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"

#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"


Enumeration Type Documentation

enum output_format

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 3442 of file manager.c.

03442                    {
03443    FORMAT_RAW,
03444    FORMAT_HTML,
03445    FORMAT_XML,
03446 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 4016 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_CERTFILE, ast_cli_register_multiple(), ast_config_load2(), ast_extension_state_add(), ast_free, ast_gethostbyname(), ast_log(), ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), ast_tls_config::certfile, ast_tls_config::cipher, cli_manager, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, 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, hp, inet_aton(), ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_modulecheck(), manager_moduleload(), manager_state_cb(), mandescr_createconfig, mandescr_getconfig, mandescr_getconfigjson, mandescr_listcategories, mandescr_ping, mandescr_updateconfig, mandescr_waitevent, and var.

Referenced by init_manager(), and reload_manager().

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

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

References AST_LIST_INSERT_HEAD, and s.

04342 {
04343    AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
04344 
04345    return 0;
04346 }

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

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

References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_datastore::info, s, and ast_datastore::uid.

04354 {
04355    struct ast_datastore *datastore = NULL;
04356    
04357    if (info == NULL)
04358       return NULL;
04359 
04360    AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
04361       if (datastore->info != info) {
04362          continue;
04363       }
04364 
04365       if (uid == NULL) {
04366          /* matched by type only */
04367          break;
04368       }
04369 
04370       if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
04371          /* Matched by type AND uid */
04372          break;
04373       }
04374    }
04375    AST_LIST_TRAVERSE_SAFE_END;
04376 
04377    return datastore;
04378 }

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

References AST_LIST_REMOVE, and s.

04349 {
04350    return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
04351 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3480 of file manager.c.

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

Referenced by handle_uri(), and static_callback().

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

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

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

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

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

static int compress_char ( char  c  )  [static]

Definition at line 3599 of file manager.c.

Referenced by member_hash_fn(), and variable_count_hash_fn().

03600 {
03601    c &= 0x7f;
03602    if (c < 32)
03603       return 0;
03604    else if (c >= 'a' && c <= 'z')
03605       return c - 64;
03606    else if (c > 'z')
03607       return '_';
03608    else
03609       return c - 32;
03610 }

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

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

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

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

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]

Definition at line 3763 of file manager.c.

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

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

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

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4331 of file manager.c.

References __init_manager().

Referenced by main().

04332 {
04333    return __init_manager(0);
04334 }

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]

Definition at line 3940 of file manager.c.

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

03941 {
03942    return generic_http_callback(FORMAT_HTML, &ser->remote_address, uri, method, params, status, title, contentlength);
03943 }

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]

Definition at line 3945 of file manager.c.

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

03946 {
03947    return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
03948 }

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

References purge_events(), and purge_sessions().

03989 {
03990    purge_sessions(1);
03991    purge_events();
03992 }

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]

Definition at line 3950 of file manager.c.

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

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

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4336 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04337 {
04338    return __init_manager(1);
04339 }

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

Definition at line 3624 of file manager.c.

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

Referenced by xml_translate().

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

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

Definition at line 3612 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

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

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

Definition at line 3538 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

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

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 3663 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(), and xml_copy_escape().

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


Variable Documentation

struct ast_tcptls_session_args ami_desc [static]

Definition at line 3995 of file manager.c.

Referenced by __init_manager().

struct ast_tls_config ami_tls_cfg

Definition at line 3994 of file manager.c.

Referenced by __init_manager().

struct ast_tcptls_session_args amis_desc [static]

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

struct ast_http_uri manageruri

Definition at line 3964 of file manager.c.

struct ast_http_uri managerxmluri

Definition at line 3973 of file manager.c.

struct ast_http_uri rawmanuri

Definition at line 3955 of file manager.c.

int registered = 0 [static]

Definition at line 3982 of file manager.c.

int webregged = 0 [static]

Definition at line 3983 of file manager.c.

char* words[AST_MAX_CMD_LEN]

Definition at line 145 of file manager.c.

Referenced by check_blacklist(), and fix_complete_args().


Generated on Fri Jun 19 12:10:41 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7