Wed Oct 28 11:46:13 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 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  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 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\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"

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 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_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,...)
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 *requestor, const char *uri, 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 char *uri, struct ast_variable *params, 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 char *uri, struct ast_variable *params, 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 char *uri, struct ast_variable *params, 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 server_args ami_desc
struct ast_tls_config ami_tls_cfg
static struct server_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_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_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\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>"

Referenced by generic_http_callback().


Enumeration Type Documentation

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 3246 of file manager.c.

03246                    {
03247    FORMAT_RAW,
03248    FORMAT_HTML,
03249    FORMAT_XML,
03250 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 3801 of file manager.c.

References 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_load, 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_register, 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_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, LOG_NOTICE, LOG_WARNING, manager_event, manager_modulecheck(), manager_moduleload(), manager_state_cb(), manageruri, managerxmluri, 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_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, ast_variable::name, ast_variable::next, rawmanuri, ast_manager_user::readperm, registered, ast_manager_user::secret, server_args::sin, server_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().

03802 {
03803    struct ast_config *ucfg = NULL, *cfg = NULL;
03804    const char *val;
03805    char *cat = NULL;
03806    int newhttptimeout = 60;
03807    int have_sslbindaddr = 0;
03808    struct hostent *hp;
03809    struct ast_hostent ahp;
03810    struct ast_manager_user *user = NULL;
03811    struct ast_variable *var;
03812    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
03813 
03814    manager_enabled = 0;
03815 
03816    if (!registered) {
03817       /* Register default actions */
03818       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
03819       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
03820       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
03821       ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
03822       ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
03823       ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
03824       ast_manager_register("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status" );
03825       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
03826       ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar );
03827       ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
03828       ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson);
03829       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
03830       ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig);
03831       ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories);
03832       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
03833       ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate);
03834       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
03835       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
03836       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
03837       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
03838       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
03839       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
03840       ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
03841       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
03842       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
03843       ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
03844       ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
03845       ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload);
03846       ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels);
03847       ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload);
03848       ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck);
03849 
03850       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
03851       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
03852       registered = 1;
03853       /* Append placeholder event so master_eventq never runs dry */
03854       append_event("Event: Placeholder\r\n\r\n", 0);
03855    }
03856    if ((cfg = ast_config_load("manager.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
03857       return 0;
03858 
03859    displayconnects = 1;
03860    if (!cfg) {
03861       ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf. Asterisk management interface (AMI) disabled.\n");
03862       return 0;
03863    }
03864 
03865    /* default values */
03866    memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in));
03867    memset(&amis_desc.sin, 0, sizeof(amis_desc.sin));
03868    amis_desc.sin.sin_port = htons(5039);
03869    ami_desc.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
03870 
03871    ami_tls_cfg.enabled = 0;
03872    if (ami_tls_cfg.certfile)
03873       ast_free(ami_tls_cfg.certfile);
03874    ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
03875    if (ami_tls_cfg.cipher)
03876       ast_free(ami_tls_cfg.cipher);
03877    ami_tls_cfg.cipher = ast_strdup("");
03878 
03879    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
03880       val = var->value;
03881       if (!strcasecmp(var->name, "sslenable"))
03882          ami_tls_cfg.enabled = ast_true(val);
03883       else if (!strcasecmp(var->name, "sslbindport"))
03884          amis_desc.sin.sin_port = htons(atoi(val));
03885       else if (!strcasecmp(var->name, "sslbindaddr")) {
03886          if ((hp = ast_gethostbyname(val, &ahp))) {
03887             memcpy(&amis_desc.sin.sin_addr, hp->h_addr, sizeof(amis_desc.sin.sin_addr));
03888             have_sslbindaddr = 1;
03889          } else {
03890             ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
03891          }
03892       } else if (!strcasecmp(var->name, "sslcert")) {
03893          ast_free(ami_tls_cfg.certfile);
03894          ami_tls_cfg.certfile = ast_strdup(val);
03895       } else if (!strcasecmp(var->name, "sslcipher")) {
03896          ast_free(ami_tls_cfg.cipher);
03897          ami_tls_cfg.cipher = ast_strdup(val);
03898       } else if (!strcasecmp(var->name, "enabled")) {
03899          manager_enabled = ast_true(val);
03900       } else if (!strcasecmp(var->name, "block-sockets")) {
03901          block_sockets = ast_true(val);
03902       } else if (!strcasecmp(var->name, "webenabled")) {
03903          webmanager_enabled = ast_true(val);
03904       } else if (!strcasecmp(var->name, "port")) {
03905          ami_desc.sin.sin_port = htons(atoi(val));
03906       } else if (!strcasecmp(var->name, "bindaddr")) {
03907          if (!inet_aton(val, &ami_desc.sin.sin_addr)) {
03908             ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03909             memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr));
03910          }
03911       } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 
03912          allowmultiplelogin = ast_true(val);
03913       } else if (!strcasecmp(var->name, "displayconnects")) {
03914          displayconnects = ast_true(val);
03915       } else if (!strcasecmp(var->name, "timestampevents")) {
03916          timestampevents = ast_true(val);
03917       } else if (!strcasecmp(var->name, "debug")) {
03918          manager_debug = ast_true(val);
03919       } else if (!strcasecmp(var->name, "httptimeout")) {
03920          newhttptimeout = atoi(val);
03921       } else {
03922          ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
03923             var->name, val);
03924       }  
03925    }
03926 
03927    if (manager_enabled)
03928       ami_desc.sin.sin_family = AF_INET;
03929    if (!have_sslbindaddr)
03930       amis_desc.sin.sin_addr = ami_desc.sin.sin_addr;
03931    if (ami_tls_cfg.enabled)
03932       amis_desc.sin.sin_family = AF_INET;
03933 
03934    
03935    AST_RWLIST_WRLOCK(&users);
03936 
03937    /* First, get users from users.conf */
03938    ucfg = ast_config_load("users.conf", config_flags);
03939    if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED)) {
03940       const char *hasmanager;
03941       int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
03942 
03943       while ((cat = ast_category_browse(ucfg, cat))) {
03944          if (!strcasecmp(cat, "general"))
03945             continue;
03946          
03947          hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
03948          if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
03949             const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
03950             const char *user_read = ast_variable_retrieve(ucfg, cat, "read");
03951             const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
03952             const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
03953             const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
03954             
03955             /* Look for an existing entry,
03956              * if none found - create one and add it to the list
03957              */
03958             if (!(user = get_manager_by_name_locked(cat))) {
03959                if (!(user = ast_calloc(1, sizeof(*user))))
03960                   break;
03961 
03962                /* Copy name over */
03963                ast_copy_string(user->username, cat, sizeof(user->username));
03964                /* Insert into list */
03965                AST_LIST_INSERT_TAIL(&users, user, list);
03966                user->ha = NULL;
03967                user->keep = 1;
03968                user->readperm = -1;
03969                user->writeperm = -1;
03970                /* Default displayconnect from [general] */
03971                user->displayconnects = displayconnects;
03972                user->writetimeout = 100;
03973             }
03974 
03975             if (!user_secret)
03976                user_secret = ast_variable_retrieve(ucfg, "general", "secret");
03977             if (!user_read)
03978                user_read = ast_variable_retrieve(ucfg, "general", "read");
03979             if (!user_write)
03980                user_write = ast_variable_retrieve(ucfg, "general", "write");
03981             if (!user_displayconnects)
03982                user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
03983             if (!user_writetimeout)
03984                user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
03985 
03986             if (!ast_strlen_zero(user_secret)) {
03987                if (user->secret)
03988                   ast_free(user->secret);
03989                user->secret = ast_strdup(user_secret);
03990             }
03991 
03992             if (user_read)
03993                user->readperm = get_perm(user_read);
03994             if (user_write)
03995                user->writeperm = get_perm(user_write);
03996             if (user_displayconnects)
03997                user->displayconnects = ast_true(user_displayconnects);
03998 
03999             if (user_writetimeout) {
04000                int val = atoi(user_writetimeout);
04001                if (val < 100)
04002                   ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
04003                else
04004                   user->writetimeout = val;
04005             }
04006          }
04007       }
04008       ast_config_destroy(ucfg);
04009    }
04010 
04011    /* cat is NULL here in any case */
04012 
04013    while ((cat = ast_category_browse(cfg, cat))) {
04014       struct ast_ha *oldha;
04015 
04016       if (!strcasecmp(cat, "general"))
04017          continue;
04018 
04019       /* Look for an existing entry, if none found - create one and add it to the list */
04020       if (!(user = get_manager_by_name_locked(cat))) {
04021          if (!(user = ast_calloc(1, sizeof(*user))))
04022             break;
04023          /* Copy name over */
04024          ast_copy_string(user->username, cat, sizeof(user->username));
04025 
04026          user->ha = NULL;
04027          user->readperm = 0;
04028          user->writeperm = 0;
04029          /* Default displayconnect from [general] */
04030          user->displayconnects = displayconnects;
04031          user->writetimeout = 100;
04032 
04033          /* Insert into list */
04034          AST_RWLIST_INSERT_TAIL(&users, user, list);
04035       }
04036 
04037       /* Make sure we keep this user and don't destroy it during cleanup */
04038       user->keep = 1;
04039       oldha = user->ha;
04040       user->ha = NULL;
04041 
04042       var = ast_variable_browse(cfg, cat);
04043       for (; var; var = var->next) {
04044          if (!strcasecmp(var->name, "secret")) {
04045             if (user->secret)
04046                ast_free(user->secret);
04047             user->secret = ast_strdup(var->value);
04048          } else if (!strcasecmp(var->name, "deny") ||
04049                    !strcasecmp(var->name, "permit")) {
04050             user->ha = ast_append_ha(var->name, var->value, user->ha, NULL);
04051          }  else if (!strcasecmp(var->name, "read") ) {
04052             user->readperm = get_perm(var->value);
04053          }  else if (!strcasecmp(var->name, "write") ) {
04054             user->writeperm = get_perm(var->value);
04055          }  else if (!strcasecmp(var->name, "displayconnects") ) {
04056             user->displayconnects = ast_true(var->value);
04057          } else if (!strcasecmp(var->name, "writetimeout")) {
04058             int val = atoi(var->value);
04059             if (val < 100)
04060                ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
04061             else
04062                user->writetimeout = val;
04063          } else
04064             ast_debug(1, "%s is an unknown option.\n", var->name);
04065       }
04066       ast_free_ha(oldha);
04067    }
04068    ast_config_destroy(cfg);
04069 
04070    /* Perform cleanup - essentially prune out old users that no longer exist */
04071    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
04072       if (user->keep) { /* valid record. clear flag for the next round */
04073          user->keep = 0;
04074          continue;
04075       }
04076       /* We do not need to keep this user so take them out of the list */
04077       AST_RWLIST_REMOVE_CURRENT(list);
04078       /* Free their memory now */
04079       if (user->secret)
04080          ast_free(user->secret);
04081       ast_free_ha(user->ha);
04082       ast_free(user);
04083    }
04084    AST_RWLIST_TRAVERSE_SAFE_END;
04085 
04086    AST_RWLIST_UNLOCK(&users);
04087 
04088    if (webmanager_enabled && manager_enabled) {
04089       if (!webregged) {
04090          ast_http_uri_link(&rawmanuri);
04091          ast_http_uri_link(&manageruri);
04092          ast_http_uri_link(&managerxmluri);
04093          webregged = 1;
04094       }
04095    } else {
04096       if (webregged) {
04097          ast_http_uri_unlink(&rawmanuri);
04098          ast_http_uri_unlink(&manageruri);
04099          ast_http_uri_unlink(&managerxmluri);
04100          webregged = 0;
04101       }
04102    }
04103 
04104    if (newhttptimeout > 0)
04105       httptimeout = newhttptimeout;
04106 
04107    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
04108 
04109    ast_tcptls_server_start(&ami_desc);
04110    if (ast_ssl_setup(amis_desc.tls_cfg))
04111       ast_tcptls_server_start(&amis_desc);
04112    return 0;
04113 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 3284 of file manager.c.

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

Referenced by static_callback().

03285 {
03286    int authed;
03287    struct mansession_session *session;
03288 
03289    if (!(session = find_session(ident, 0)))
03290       return 0;
03291 
03292    authed = (session->authenticated != 0);
03293 
03294    ast_mutex_unlock(&session->__lock);
03295 
03296    return authed;
03297 }

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

03300 {
03301    int result = 0;
03302    struct mansession_session *session;
03303 
03304    AST_LIST_LOCK(&sessions);
03305    AST_LIST_TRAVERSE(&sessions, session, list) {
03306       ast_mutex_lock(&session->__lock);
03307       if ((session->managerid == ident) && (session->readperm & perm)) {
03308          result = 1;
03309          ast_mutex_unlock(&session->__lock);
03310          break;
03311       }
03312       ast_mutex_unlock(&session->__lock);
03313    }
03314    AST_LIST_UNLOCK(&sessions);
03315    return result;
03316 }

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

03319 {
03320    int result = 0;
03321    struct mansession_session *session;
03322 
03323    AST_LIST_LOCK(&sessions);
03324    AST_LIST_TRAVERSE(&sessions, session, list) {
03325       ast_mutex_lock(&session->__lock);
03326       if ((session->managerid == ident) && (session->writeperm & perm)) {
03327          result = 1;
03328          ast_mutex_unlock(&session->__lock);
03329          break;
03330       }
03331       ast_mutex_unlock(&session->__lock);
03332    }
03333    AST_LIST_UNLOCK(&sessions);
03334    return result;
03335 }

static int compress_char ( char  c  )  [static]

Definition at line 3403 of file manager.c.

Referenced by member_hash_fn(), and variable_count_hash_fn().

03404 {
03405    c &= 0x7f;
03406    if (c < 32)
03407       return 0;
03408    else if (c >= 'a' && c <= 'z')
03409       return c - 64;
03410    else if (c > 'z')
03411       return '_';
03412    else
03413       return c - 32;
03414 }

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

03264 {
03265    struct mansession_session *session;
03266 
03267    if (ident == 0)
03268       return NULL;
03269 
03270    AST_LIST_LOCK(&sessions);
03271    AST_LIST_TRAVERSE(&sessions, session, list) {
03272       ast_mutex_lock(&session->__lock);
03273       if (session->managerid == ident && !session->needdestroy) {
03274          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
03275          break;
03276       }
03277       ast_mutex_unlock(&session->__lock);
03278    }
03279    AST_LIST_UNLOCK(&sessions);
03280 
03281    return session;
03282 }

static struct ast_str* generic_http_callback ( enum output_format  format,
struct sockaddr_in *  requestor,
const char *  uri,
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 3567 of file manager.c.

References mansession_session::__lock, ast_atomic_fetchadd_int(), ast_calloc, ast_debug, ast_http_error(), ast_inet_ntoa(), 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().

03571 {
03572    struct mansession s = {.session = NULL, };
03573    struct mansession_session *session = NULL;
03574    uint32_t ident = 0;
03575    int blastaway = 0;
03576    struct ast_variable *v;
03577    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
03578    struct ast_str *out = NULL;
03579    struct message m = { 0 };
03580    unsigned int x;
03581    size_t hdrlen;
03582 
03583    for (v = params; v; v = v->next) {
03584       if (!strcasecmp(v->name, "mansession_id")) {
03585          sscanf(v->value, "%30x", &ident);
03586          break;
03587       }
03588    }
03589 
03590    if (!(session = find_session(ident, 1))) {
03591       /* Create new session.
03592        * While it is not in the list we don't need any locking
03593        */
03594       if (!(session = ast_calloc(1, sizeof(*session)))) {
03595          *status = 500;
03596          goto generic_callback_out;
03597       }
03598       session->sin = *requestor;
03599       session->fd = -1;
03600       session->waiting_thread = AST_PTHREADT_NULL;
03601       session->send_events = 0;
03602       ast_mutex_init(&session->__lock);
03603       ast_mutex_lock(&session->__lock);
03604       session->inuse = 1;
03605       /*!\note There is approximately a 1 in 1.8E19 chance that the following
03606        * calculation will produce 0, which is an invalid ID, but due to the
03607        * properties of the rand() function (and the constantcy of s), that
03608        * won't happen twice in a row.
03609        */
03610       while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
03611       session->last_ev = grab_last();
03612       AST_LIST_LOCK(&sessions);
03613       AST_LIST_INSERT_HEAD(&sessions, session, list);
03614       ast_atomic_fetchadd_int(&num_sessions, 1);
03615       AST_LIST_UNLOCK(&sessions);
03616    }
03617 
03618    s.session = session;
03619 
03620    ast_mutex_unlock(&session->__lock);
03621 
03622    if (!(out = ast_str_create(1024))) {
03623       *status = 500;
03624       goto generic_callback_out;
03625    }
03626 
03627    s.fd = mkstemp(template);  /* create a temporary file for command output */
03628    unlink(template);
03629    s.f = fdopen(s.fd, "w+");
03630 
03631    for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
03632       hdrlen = strlen(v->name) + strlen(v->value) + 3;
03633       m.headers[m.hdrcount] = alloca(hdrlen);
03634       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
03635       m.hdrcount = x + 1;
03636    }
03637 
03638    if (process_message(&s, &m)) {
03639       if (session->authenticated) {
03640             if (manager_displayconnects(session))
03641             ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03642          ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03643       } else {
03644             if (displayconnects)
03645             ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
03646          ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
03647       }
03648       session->needdestroy = 1;
03649    }
03650 
03651    ast_str_append(&out, 0,
03652              "Content-type: text/%s\r\n"
03653              "Cache-Control: no-cache;\r\n"
03654              "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n"
03655              "\r\n",
03656          contenttype[format],
03657          session->managerid, httptimeout);
03658 
03659    if (format == FORMAT_XML) {
03660       ast_str_append(&out, 0, "<ajax-response>\n");
03661    } else if (format == FORMAT_HTML) {
03662 
03663 #define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
03664 #define TEST_STRING \
03665    "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \
03666    user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \
03667    <input type=\"submit\"></form>"
03668 
03669       ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
03670       ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
03671       ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
03672       ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
03673    }
03674 
03675    if (s.f != NULL) {   /* have temporary output */
03676       char *buf;
03677       size_t l;
03678       
03679       /* Ensure buffer is NULL-terminated */
03680       fprintf(s.f, "%c", 0);
03681 
03682       if ((l = ftell(s.f))) {
03683          if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
03684             ast_log(LOG_WARNING, "mmap failed.  Manager output was not processed\n");
03685          } else {
03686             if (format == FORMAT_XML || format == FORMAT_HTML)
03687                xml_translate(&out, buf, params, format);
03688             else
03689                ast_str_append(&out, 0, "%s", buf);
03690             munmap(buf, l);
03691          }
03692       } else if (format == FORMAT_XML || format == FORMAT_HTML) {
03693          xml_translate(&out, "", params, format);
03694       }
03695       fclose(s.f);
03696       s.f = NULL;
03697       s.fd = -1;
03698    }
03699 
03700    if (format == FORMAT_XML) {
03701       ast_str_append(&out, 0, "</ajax-response>\n");
03702    } else if (format == FORMAT_HTML)
03703       ast_str_append(&out, 0, "</table></body>\r\n");
03704 
03705    ast_mutex_lock(&session->__lock);
03706    /* Reset HTTP timeout.  If we're not authenticated, keep it extremely short */
03707    session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
03708 
03709    if (session->needdestroy) {
03710       if (session->inuse == 1) {
03711          ast_debug(1, "Need destroy, doing it now!\n");
03712          blastaway = 1;
03713       } else {
03714          ast_debug(1, "Need destroy, but can't do it yet!\n");
03715          if (session->waiting_thread != AST_PTHREADT_NULL)
03716             pthread_kill(session->waiting_thread, SIGURG);
03717          session->inuse--;
03718       }
03719    } else
03720       session->inuse--;
03721    ast_mutex_unlock(&session->__lock);
03722 
03723    if (blastaway)
03724       destroy_session(session);
03725 generic_callback_out:
03726    if (*status != 200)
03727       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
03728    return out;
03729 }

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 4115 of file manager.c.

References __init_manager().

Referenced by main().

04116 {
04117    return __init_manager(0);
04118 }

static struct ast_str* manager_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3731 of file manager.c.

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

03732 {
03733    return generic_http_callback(FORMAT_HTML, &ser->requestor, uri, params, status, title, contentlength);
03734 }

static struct ast_str* mxml_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3736 of file manager.c.

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

03737 {
03738    return generic_http_callback(FORMAT_XML, &ser->requestor, uri, params, status, title, contentlength);
03739 }

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

References purge_events(), and purge_sessions().

03774 {
03775    purge_sessions(1);
03776    purge_events();
03777 }

static struct ast_str* rawman_http_callback ( struct ast_tcptls_session_instance ser,
const char *  uri,
struct ast_variable params,
int *  status,
char **  title,
int *  contentlength 
) [static, read]

Definition at line 3741 of file manager.c.

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

03742 {
03743    return generic_http_callback(FORMAT_RAW, &ser->requestor, uri, params, status, title, contentlength);
03744 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 4120 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

04121 {
04122    return __init_manager(1);
04123 }

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

Definition at line 3428 of file manager.c.

References CMP_MATCH, str, and variable_count::varname.

Referenced by xml_translate().

03429 {
03430    /* Due to the simplicity of struct variable_count, it makes no difference
03431     * if you pass in objects or strings, the same operation applies. This is
03432     * due to the fact that the hash occurs on the first element, which means
03433     * the address of both the struct and the string are exactly the same. */
03434    struct variable_count *vc = obj;
03435    char *str = vstr;
03436    return !strcmp(vc->varname, str) ? CMP_MATCH : 0;
03437 }

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

Definition at line 3416 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

03417 {
03418    const struct variable_count *vc = vvc;
03419    int res = 0, i;
03420    for (i = 0; i < 5; i++) {
03421       if (vc->varname[i] == '\0')
03422          break;
03423       res += compress_char(vc->varname[i]) << (i * 6);
03424    }
03425    return res;
03426 }

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

Definition at line 3342 of file manager.c.

References ast_str_append(), and buf.

Referenced by xml_translate().

03343 {
03344    /* store in a local buffer to avoid calling ast_str_append too often */
03345    char buf[256];
03346    char *dst = buf;
03347    int space = sizeof(buf);
03348    /* repeat until done and nothing to flush */
03349    for ( ; *src || dst != buf ; src++) {
03350       if (*src == '\0' || space < 10) {   /* flush */
03351          *dst++ = '\0';
03352          ast_str_append(out, 0, "%s", buf);
03353          dst = buf;
03354          space = sizeof(buf);
03355          if (*src == '\0')
03356             break;
03357       }
03358          
03359       if ( (mode & 2) && !isalnum(*src)) {
03360          *dst++ = '_';
03361          space--;
03362          continue;
03363       }
03364       switch (*src) {
03365       case '<':
03366          strcpy(dst, "&lt;");
03367          dst += 4;
03368          space -= 4;
03369          break;
03370       case '>':
03371          strcpy(dst, "&gt;");
03372          dst += 4;
03373          space -= 4;
03374          break;
03375       case '\"':
03376          strcpy(dst, "&quot;");
03377          dst += 6;
03378          space -= 6;
03379          break;
03380       case '\'':
03381          strcpy(dst, "&apos;");
03382          dst += 6;
03383          space -= 6;
03384          break;
03385       case '&':
03386          strcpy(dst, "&amp;");
03387          dst += 5;
03388          space -= 5;
03389          break;
03390 
03391       default:
03392          *dst++ = mode ? tolower(*src) : *src;
03393          space--;
03394       }
03395    }
03396 }

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

03468 {
03469    struct ast_variable *v;
03470    const char *dest = NULL;
03471    char *var, *val;
03472    const char *objtype = NULL;
03473    int in_data = 0;  /* parsing data */
03474    int inobj = 0;
03475    int xml = (format == FORMAT_XML);
03476    struct variable_count *vc = NULL;
03477    struct ao2_container *vco = NULL;
03478 
03479    for (v = vars; v; v = v->next) {
03480       if (!dest && !strcasecmp(v->name, "ajaxdest"))
03481          dest = v->value;
03482       else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
03483          objtype = v->value;
03484    }
03485    if (!dest)
03486       dest = "unknown";
03487    if (!objtype)
03488       objtype = "generic";
03489 
03490    /* we want to stop when we find an empty line */
03491    while (in && *in) {
03492       val = strsep(&in, "\r\n"); /* mark start and end of line */
03493       if (in && *in == '\n')     /* remove trailing \n if any */
03494          in++;
03495       ast_trim_blanks(val);
03496       ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
03497       if (ast_strlen_zero(val)) {
03498          if (in_data) { /* close data */
03499             ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03500             in_data = 0;
03501          }
03502          if (inobj) {
03503             ast_str_append(out, 0, xml ? " /></response>\n" :
03504                "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03505             inobj = 0;
03506             ao2_ref(vco, -1);
03507             vco = NULL;
03508          }
03509          continue;
03510       }
03511 
03512       /* we expect Name: value lines */
03513       if (in_data) {
03514          var = NULL;
03515       } else {
03516          var = strsep(&val, ":");
03517          if (val) {  /* found the field name */
03518             val = ast_skip_blanks(val);
03519             ast_trim_blanks(var);
03520          } else {    /* field name not found, move to opaque mode */
03521             val = var;
03522             var = "Opaque-data";
03523          }
03524       }
03525 
03526       if (!inobj) {
03527          if (xml)
03528             ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
03529          else
03530             ast_str_append(out, 0, "<body>\n");
03531          vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
03532          inobj = 1;
03533       }
03534 
03535       if (!in_data) {   /* build appropriate line start */
03536          ast_str_append(out, 0, xml ? " " : "<tr><td>");
03537          if ((vc = ao2_find(vco, var, 0)))
03538             vc->count++;
03539          else {
03540             /* Create a new entry for this one */
03541             vc = ao2_alloc(sizeof(*vc), NULL);
03542             vc->varname = var;
03543             vc->count = 1;
03544             ao2_link(vco, vc);
03545          }
03546          xml_copy_escape(out, var, xml ? 1 | 2 : 0);
03547          if (vc->count > 1)
03548             ast_str_append(out, 0, "-%d", vc->count);
03549          ao2_ref(vc, -1);
03550          ast_str_append(out, 0, xml ? "='" : "</td><td>");
03551          if (!strcmp(var, "Opaque-data"))
03552             in_data = 1;
03553       }
03554       xml_copy_escape(out, val, 0); /* data field */
03555       if (!in_data)
03556          ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
03557       else
03558          ast_str_append(out, 0, xml ? "\n" : "<br>\n");
03559    }
03560    if (inobj) {
03561       ast_str_append(out, 0, xml ? " /></response>\n" :
03562          "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
03563       ao2_ref(vco, -1);
03564    }
03565 }


Variable Documentation

struct server_args ami_desc [static]

Definition at line 3780 of file manager.c.

Referenced by __init_manager().

Definition at line 3779 of file manager.c.

Referenced by __init_manager().

struct server_args amis_desc [static]

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

Referenced by generic_http_callback().

Definition at line 3753 of file manager.c.

Referenced by __init_manager().

Definition at line 3760 of file manager.c.

Referenced by __init_manager().

Definition at line 3746 of file manager.c.

Referenced by __init_manager().

int registered = 0 [static]

Definition at line 3767 of file manager.c.

Referenced by __init_manager().

int webregged = 0 [static]

Definition at line 3768 of file manager.c.

Referenced by __init_manager().

char* words[AST_MAX_CMD_LEN]

Definition at line 144 of file manager.c.

Referenced by check_blacklist().


Generated on Wed Oct 28 11:46:13 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6