Thu Dec 17 17:40:55 2009

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(), 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 2875 of file manager.c.

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

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

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

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

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

int init_manager ( void   ) 

Called by Asterisk initialization

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

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

int reload_manager ( void   ) 

Definition at line 3448 of file manager.c.

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

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


Generated on Thu Dec 17 17:40:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7