Thu Mar 25 10:39:28 2010

Asterisk developer's documentation


manager.h File Reference

The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party software. More...

#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/lock.h"

Go to the source code of this file.

Data Structures

struct  manager_action
struct  message

Defines

#define AMI_VERSION   "1.0"
#define ast_manager_register(a, b, c, d)   ast_manager_register2(a, b, c, d, NULL)
#define AST_MAX_MANHEADERS   128
#define DEFAULT_MANAGER_PORT   5038
#define EVENT_FLAG_AGENT   (1 << 5)
#define EVENT_FLAG_CALL   (1 << 1)
#define EVENT_FLAG_COMMAND   (1 << 4)
#define EVENT_FLAG_CONFIG   (1 << 7)
#define EVENT_FLAG_LOG   (1 << 2)
#define EVENT_FLAG_SYSTEM   (1 << 0)
#define EVENT_FLAG_USER   (1 << 6)
#define EVENT_FLAG_VERBOSE   (1 << 3)

Functions

int ast_manager_register2 (const char *action, int authority, 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
int ast_manager_unregister (char *action)
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
ast_variableastman_get_variables (const struct message *m)
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
void astman_send_error (struct mansession *s, const struct message *m, char *error)
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
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.
int check_manager_enabled (void)
 Check if AMI is enabled.
int check_webmanager_enabled (void)
 Check if AMI/HTTP is enabled.
int init_manager (void)
int manager_event (int category, const char *event, const char *contents,...)
 manager_event: Send AMI event to client
int reload_manager (void)


Detailed Description

The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party software.

Manager protocol packages are text fields of the form a: b. There is always exactly one space after the colon.

The first header type is the "Event" header. Other headers vary from event to event. Headers end with standard
termination. The last line of the manager response or event is an empty line. (
)

Please try to re-use existing headers to simplify manager message parsing in clients. Don't re-use an existing header with a new meaning, please. You can find a reference of standard headers in doc/manager.txt

Definition in file manager.h.


Define Documentation

#define AMI_VERSION   "1.0"

Definition at line 48 of file manager.h.

Referenced by action_coresettings().

#define ast_manager_register ( a,
b,
c,
 )     ast_manager_register2(a, b, c, d, NULL)

Definition at line 92 of file manager.h.

Referenced by astdb_init(), init_manager(), and load_module().

#define AST_MAX_MANHEADERS   128

Definition at line 61 of file manager.h.

Referenced by do_message().

#define DEFAULT_MANAGER_PORT   5038

Definition at line 49 of file manager.h.

Referenced by init_manager().

#define EVENT_FLAG_AGENT   (1 << 5)

Definition at line 56 of file manager.h.

Referenced by __login_exec(), action_agent_callback_login(), add_to_queue(), agent_logoff_maintenance(), load_module(), record_abandoned(), remove_from_queue(), ring_entry(), set_member_paused(), try_calling(), and update_status().

#define EVENT_FLAG_CALL   (1 << 1)

Definition at line 52 of file manager.h.

Referenced by change_hold_state(), conf_run(), fast_originate(), init_manager(), join_queue(), leave_queue(), load_module(), manager_log(), manager_state_cb(), notify_new_message(), park_call_full(), park_exec(), pbx_extension_helper(), post_manager_event(), realtime_exec(), send_talking_event(), senddialevent(), socket_process(), and vm_execmain().

#define EVENT_FLAG_COMMAND   (1 << 4)

Definition at line 55 of file manager.h.

Referenced by init_manager().

#define EVENT_FLAG_CONFIG   (1 << 7)

Definition at line 58 of file manager.h.

Referenced by init_manager().

#define EVENT_FLAG_LOG   (1 << 2)

Definition at line 53 of file manager.h.

#define EVENT_FLAG_SYSTEM   (1 << 0)

Definition at line 51 of file manager.h.

Referenced by __expire_registry(), __iax2_poke_noanswer(), ast_log(), astdb_init(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), expire_register(), handle_alarms(), handle_init_event(), handle_response_peerpoke(), handle_response_register(), iax2_ack_registry(), init_manager(), load_module(), parse_register_contact(), quit_handler(), register_verify(), reload_logger(), reload_manager(), sip_poke_noanswer(), sip_reg_timeout(), socket_process(), ss_thread(), and update_registry().

#define EVENT_FLAG_USER   (1 << 6)

Definition at line 57 of file manager.h.

Referenced by aji_log_hook(), and init_manager().

#define EVENT_FLAG_VERBOSE   (1 << 3)

Definition at line 54 of file manager.h.


Function Documentation

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
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2876 of file manager.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.

02877 {
02878    int result = 0;
02879    struct mansession_session *s;
02880 
02881    AST_LIST_LOCK(&sessions);
02882    AST_LIST_TRAVERSE(&sessions, s, list) {
02883       ast_mutex_lock(&s->__lock);
02884       if ((s->managerid == ident) && (s->readperm & perm)) {
02885          result = 1;
02886          ast_mutex_unlock(&s->__lock);
02887          break;
02888       }
02889       ast_mutex_unlock(&s->__lock);
02890    }
02891    AST_LIST_UNLOCK(&sessions);
02892    return result;
02893 }

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
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2895 of file manager.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.

02896 {
02897    int result = 0;
02898    struct mansession_session *s;
02899 
02900    AST_LIST_LOCK(&sessions);
02901    AST_LIST_TRAVERSE(&sessions, s, list) {
02902       ast_mutex_lock(&s->__lock);
02903       if ((s->managerid == ident) && (s->writeperm & perm)) {
02904          result = 1;
02905          ast_mutex_unlock(&s->__lock);
02906          break;
02907       }
02908       ast_mutex_unlock(&s->__lock);
02909    }
02910    AST_LIST_UNLOCK(&sessions);
02911    return result;
02912 }

int init_manager ( void   ) 

Called by Asterisk initialization

Definition at line 3157 of file manager.c.

References action_atxfer(), action_command(), action_coresettings(), action_corestatus(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), append_event(), asock, ast_calloc, ast_category_browse(), ast_cli_register_multiple(), ast_config_load(), ast_copy_string(), ast_extension_state_add(), ast_get_manager_by_name_locked(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), ast_variable_retrieve(), block_sockets, cli_manager, DEFAULT_MANAGER_PORT, ast_manager_user::deny, ast_manager_user::displayconnects, displayconnects, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, ast_channel::flags, free, ast_manager_user::keep, LOG_DEBUG, LOG_WARNING, manager_enabled, manager_state_cb(), mandescr_atxfer, mandescr_command, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getvar, mandescr_hangup, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_setvar, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, ast_manager_user::permit, portno, ast_manager_user::read, ast_manager_user::secret, timestampevents, var, webmanager_enabled, and ast_manager_user::write.

Referenced by main(), and reload_manager().

03158 {
03159    struct ast_config *cfg = NULL, *ucfg = NULL;
03160    const char *val;
03161    char *cat = NULL;
03162    int oldportno = portno;
03163    static struct sockaddr_in ba;
03164    int x = 1;
03165    int flags;
03166    int newhttptimeout = 60;
03167    struct ast_manager_user *user = NULL;
03168 
03169    if (!registered) {
03170       /* Register default actions */
03171       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
03172       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
03173       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
03174       ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
03175       ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
03176       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
03177       ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
03178       ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
03179       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
03180       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
03181       ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer );
03182       ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
03183       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
03184       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
03185       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
03186       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
03187       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
03188       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
03189       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
03190       ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
03191       ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
03192       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
03193 
03194       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
03195       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
03196       registered = 1;
03197       /* Append placeholder event so master_eventq never runs dry */
03198       append_event("Event: Placeholder\r\n\r\n", 0);
03199    }
03200    portno = DEFAULT_MANAGER_PORT;
03201    displayconnects = 1;
03202    cfg = ast_config_load("manager.conf");
03203    if (!cfg) {
03204       ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
03205       return 0;
03206    }
03207    if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) {
03208       manager_enabled = ast_true(val);
03209    }
03210    if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) {
03211       block_sockets = ast_true(val);
03212    }
03213    if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) {
03214       webmanager_enabled = ast_true(val);
03215    }
03216    if ((val = ast_variable_retrieve(cfg, "general", "port"))) {
03217       if (sscanf(val, "%5d", &portno) != 1) {
03218          ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
03219          portno = DEFAULT_MANAGER_PORT;
03220       }
03221    }
03222 
03223    if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) {
03224       displayconnects = ast_true(val);
03225    }
03226    if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) {
03227       timestampevents = ast_true(val);
03228    }
03229    if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) {
03230       newhttptimeout = atoi(val);
03231    }
03232 
03233    memset(&ba, 0, sizeof(ba));
03234    ba.sin_family = AF_INET;
03235    ba.sin_port = htons(portno);
03236 
03237    if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
03238       if (!inet_aton(val, &ba.sin_addr)) { 
03239          ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03240          memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
03241       }
03242    }
03243    
03244 
03245    if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) {
03246 #if 0
03247       /* Can't be done yet */
03248       close(asock);
03249       asock = -1;
03250 #else
03251       ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
03252 #endif
03253    }
03254 
03255    AST_LIST_LOCK(&users);
03256 
03257    if ((ucfg = ast_config_load("users.conf"))) {
03258       while ((cat = ast_category_browse(ucfg, cat))) {
03259          int hasmanager = 0;
03260          struct ast_variable *var = NULL;
03261 
03262          if (!strcasecmp(cat, "general")) {
03263             continue;
03264          }
03265 
03266          if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) {
03267             continue;
03268          }
03269 
03270          /* Look for an existing entry, if none found - create one and add it to the list */
03271          if (!(user = ast_get_manager_by_name_locked(cat))) {
03272             if (!(user = ast_calloc(1, sizeof(*user)))) {
03273                break;
03274             }
03275             /* Copy name over */
03276             ast_copy_string(user->username, cat, sizeof(user->username));
03277             /* Insert into list */
03278             AST_LIST_INSERT_TAIL(&users, user, list);
03279          }
03280 
03281          /* Make sure we keep this user and don't destroy it during cleanup */
03282          user->keep = 1;
03283 
03284          for (var = ast_variable_browse(ucfg, cat); var; var = var->next) {
03285             if (!strcasecmp(var->name, "secret")) {
03286                if (user->secret) {
03287                   free(user->secret);
03288                }
03289                user->secret = ast_strdup(var->value);
03290             } else if (!strcasecmp(var->name, "deny") ) {
03291                if (user->deny) {
03292                   free(user->deny);
03293                }
03294                user->deny = ast_strdup(var->value);
03295             } else if (!strcasecmp(var->name, "permit") ) {
03296                if (user->permit) {
03297                   free(user->permit);
03298                }
03299                user->permit = ast_strdup(var->value);
03300             } else if (!strcasecmp(var->name, "read") ) {
03301                if (user->read) {
03302                   free(user->read);
03303                }
03304                user->read = ast_strdup(var->value);
03305             } else if (!strcasecmp(var->name, "write") ) {
03306                if (user->write) {
03307                   free(user->write);
03308                }
03309                user->write = ast_strdup(var->value);
03310             } else if (!strcasecmp(var->name, "displayconnects") ) {
03311                user->displayconnects = ast_true(var->value);
03312             } else if (!strcasecmp(var->name, "hasmanager")) {
03313                /* already handled */
03314             } else {
03315                ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name);
03316             }
03317          }
03318       }
03319       ast_config_destroy(ucfg);
03320    }
03321 
03322    while ((cat = ast_category_browse(cfg, cat))) {
03323       struct ast_variable *var = NULL;
03324 
03325       if (!strcasecmp(cat, "general"))
03326          continue;
03327 
03328       /* Look for an existing entry, if none found - create one and add it to the list */
03329       if (!(user = ast_get_manager_by_name_locked(cat))) {
03330          if (!(user = ast_calloc(1, sizeof(*user))))
03331             break;
03332          /* Copy name over */
03333          ast_copy_string(user->username, cat, sizeof(user->username));
03334          /* Insert into list */
03335          AST_LIST_INSERT_TAIL(&users, user, list);
03336       }
03337 
03338       /* Make sure we keep this user and don't destroy it during cleanup */
03339       user->keep = 1;
03340 
03341       var = ast_variable_browse(cfg, cat);
03342       while (var) {
03343          if (!strcasecmp(var->name, "secret")) {
03344             if (user->secret)
03345                free(user->secret);
03346             user->secret = ast_strdup(var->value);
03347          } else if (!strcasecmp(var->name, "deny") ) {
03348             if (user->deny)
03349                free(user->deny);
03350             user->deny = ast_strdup(var->value);
03351          } else if (!strcasecmp(var->name, "permit") ) {
03352             if (user->permit)
03353                free(user->permit);
03354             user->permit = ast_strdup(var->value);
03355          }  else if (!strcasecmp(var->name, "read") ) {
03356             if (user->read)
03357                free(user->read);
03358             user->read = ast_strdup(var->value);
03359          }  else if (!strcasecmp(var->name, "write") ) {
03360             if (user->write)
03361                free(user->write);
03362             user->write = ast_strdup(var->value);
03363          }  else if (!strcasecmp(var->name, "displayconnects") )
03364             user->displayconnects = ast_true(var->value);
03365          else
03366             ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03367          var = var->next;
03368       }
03369    }
03370 
03371    /* Perform cleanup - essentially prune out old users that no longer exist */
03372    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03373       if (user->keep) {
03374          user->keep = 0;
03375          continue;
03376       }
03377       /* We do not need to keep this user so take them out of the list */
03378       AST_LIST_REMOVE_CURRENT(&users, list);
03379       /* Free their memory now */
03380       if (user->secret)
03381          free(user->secret);
03382       if (user->deny)
03383          free(user->deny);
03384       if (user->permit)
03385          free(user->permit);
03386       if (user->read)
03387          free(user->read);
03388       if (user->write)
03389          free(user->write);
03390       free(user);
03391    }
03392    AST_LIST_TRAVERSE_SAFE_END
03393 
03394    AST_LIST_UNLOCK(&users);
03395 
03396    ast_config_destroy(cfg);
03397    
03398    if (webmanager_enabled && manager_enabled) {
03399       if (!webregged) {
03400          ast_http_uri_link(&rawmanuri);
03401          ast_http_uri_link(&manageruri);
03402          ast_http_uri_link(&managerxmluri);
03403          webregged = 1;
03404       }
03405    } else {
03406       if (webregged) {
03407          ast_http_uri_unlink(&rawmanuri);
03408          ast_http_uri_unlink(&manageruri);
03409          ast_http_uri_unlink(&managerxmluri);
03410          webregged = 0;
03411       }
03412    }
03413 
03414    if (newhttptimeout > 0)
03415       httptimeout = newhttptimeout;
03416 
03417    /* If not enabled, do nothing */
03418    if (!manager_enabled)
03419       return 0;
03420 
03421    if (asock < 0) {
03422       asock = socket(AF_INET, SOCK_STREAM, 0);
03423       if (asock < 0) {
03424          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
03425          return -1;
03426       }
03427       setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
03428       if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
03429          ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
03430          close(asock);
03431          asock = -1;
03432          return -1;
03433       }
03434       if (listen(asock, 2)) {
03435          ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
03436          close(asock);
03437          asock = -1;
03438          return -1;
03439       }
03440       flags = fcntl(asock, F_GETFL);
03441       fcntl(asock, F_SETFL, flags | O_NONBLOCK);
03442       if (option_verbose)
03443          ast_verbose("Asterisk Management interface listening on port %d\n", portno);
03444       ast_pthread_create_background(&t, NULL, accept_thread, NULL);
03445    }
03446    return 0;
03447 }

int reload_manager ( void   ) 

Definition at line 3449 of file manager.c.

References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().

03450 {
03451    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03452    return init_manager();
03453 }


Generated on Thu Mar 25 10:39:28 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7