Tue Jul 14 23:10:28 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(), 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 2873 of file manager.c.

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

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

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

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

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

int init_manager ( void   ) 

Called by Asterisk initialization

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

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

int reload_manager ( void   ) 

Definition at line 3441 of file manager.c.

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

03442 {
03443    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03444    return init_manager();
03445 }


Generated on Tue Jul 14 23:10:28 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7