Wed Oct 14 15:02:20 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, "%5d", &portno) != 1) {
03211          ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
03212          portno = DEFAULT_MANAGER_PORT;
03213       }
03214    }
03215 
03216    if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) {
03217       displayconnects = ast_true(val);
03218    }
03219    if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) {
03220       timestampevents = ast_true(val);
03221    }
03222    if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) {
03223       newhttptimeout = atoi(val);
03224    }
03225 
03226    memset(&ba, 0, sizeof(ba));
03227    ba.sin_family = AF_INET;
03228    ba.sin_port = htons(portno);
03229 
03230    if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
03231       if (!inet_aton(val, &ba.sin_addr)) { 
03232          ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03233          memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
03234       }
03235    }
03236    
03237 
03238    if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) {
03239 #if 0
03240       /* Can't be done yet */
03241       close(asock);
03242       asock = -1;
03243 #else
03244       ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
03245 #endif
03246    }
03247 
03248    AST_LIST_LOCK(&users);
03249 
03250    if ((ucfg = ast_config_load("users.conf"))) {
03251       while ((cat = ast_category_browse(ucfg, cat))) {
03252          int hasmanager = 0;
03253          struct ast_variable *var = NULL;
03254 
03255          if (!strcasecmp(cat, "general")) {
03256             continue;
03257          }
03258 
03259          if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) {
03260             continue;
03261          }
03262 
03263          /* Look for an existing entry, if none found - create one and add it to the list */
03264          if (!(user = ast_get_manager_by_name_locked(cat))) {
03265             if (!(user = ast_calloc(1, sizeof(*user)))) {
03266                break;
03267             }
03268             /* Copy name over */
03269             ast_copy_string(user->username, cat, sizeof(user->username));
03270             /* Insert into list */
03271             AST_LIST_INSERT_TAIL(&users, user, list);
03272          }
03273 
03274          /* Make sure we keep this user and don't destroy it during cleanup */
03275          user->keep = 1;
03276 
03277          for (var = ast_variable_browse(ucfg, cat); var; var = var->next) {
03278             if (!strcasecmp(var->name, "secret")) {
03279                if (user->secret) {
03280                   free(user->secret);
03281                }
03282                user->secret = ast_strdup(var->value);
03283             } else if (!strcasecmp(var->name, "deny") ) {
03284                if (user->deny) {
03285                   free(user->deny);
03286                }
03287                user->deny = ast_strdup(var->value);
03288             } else if (!strcasecmp(var->name, "permit") ) {
03289                if (user->permit) {
03290                   free(user->permit);
03291                }
03292                user->permit = ast_strdup(var->value);
03293             } else if (!strcasecmp(var->name, "read") ) {
03294                if (user->read) {
03295                   free(user->read);
03296                }
03297                user->read = ast_strdup(var->value);
03298             } else if (!strcasecmp(var->name, "write") ) {
03299                if (user->write) {
03300                   free(user->write);
03301                }
03302                user->write = ast_strdup(var->value);
03303             } else if (!strcasecmp(var->name, "displayconnects") ) {
03304                user->displayconnects = ast_true(var->value);
03305             } else if (!strcasecmp(var->name, "hasmanager")) {
03306                /* already handled */
03307             } else {
03308                ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name);
03309             }
03310          }
03311       }
03312       ast_config_destroy(ucfg);
03313    }
03314 
03315    while ((cat = ast_category_browse(cfg, cat))) {
03316       struct ast_variable *var = NULL;
03317 
03318       if (!strcasecmp(cat, "general"))
03319          continue;
03320 
03321       /* Look for an existing entry, if none found - create one and add it to the list */
03322       if (!(user = ast_get_manager_by_name_locked(cat))) {
03323          if (!(user = ast_calloc(1, sizeof(*user))))
03324             break;
03325          /* Copy name over */
03326          ast_copy_string(user->username, cat, sizeof(user->username));
03327          /* Insert into list */
03328          AST_LIST_INSERT_TAIL(&users, user, list);
03329       }
03330 
03331       /* Make sure we keep this user and don't destroy it during cleanup */
03332       user->keep = 1;
03333 
03334       var = ast_variable_browse(cfg, cat);
03335       while (var) {
03336          if (!strcasecmp(var->name, "secret")) {
03337             if (user->secret)
03338                free(user->secret);
03339             user->secret = ast_strdup(var->value);
03340          } else if (!strcasecmp(var->name, "deny") ) {
03341             if (user->deny)
03342                free(user->deny);
03343             user->deny = ast_strdup(var->value);
03344          } else if (!strcasecmp(var->name, "permit") ) {
03345             if (user->permit)
03346                free(user->permit);
03347             user->permit = ast_strdup(var->value);
03348          }  else if (!strcasecmp(var->name, "read") ) {
03349             if (user->read)
03350                free(user->read);
03351             user->read = ast_strdup(var->value);
03352          }  else if (!strcasecmp(var->name, "write") ) {
03353             if (user->write)
03354                free(user->write);
03355             user->write = ast_strdup(var->value);
03356          }  else if (!strcasecmp(var->name, "displayconnects") )
03357             user->displayconnects = ast_true(var->value);
03358          else
03359             ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03360          var = var->next;
03361       }
03362    }
03363 
03364    /* Perform cleanup - essentially prune out old users that no longer exist */
03365    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03366       if (user->keep) {
03367          user->keep = 0;
03368          continue;
03369       }
03370       /* We do not need to keep this user so take them out of the list */
03371       AST_LIST_REMOVE_CURRENT(&users, list);
03372       /* Free their memory now */
03373       if (user->secret)
03374          free(user->secret);
03375       if (user->deny)
03376          free(user->deny);
03377       if (user->permit)
03378          free(user->permit);
03379       if (user->read)
03380          free(user->read);
03381       if (user->write)
03382          free(user->write);
03383       free(user);
03384    }
03385    AST_LIST_TRAVERSE_SAFE_END
03386 
03387    AST_LIST_UNLOCK(&users);
03388 
03389    ast_config_destroy(cfg);
03390    
03391    if (webmanager_enabled && manager_enabled) {
03392       if (!webregged) {
03393          ast_http_uri_link(&rawmanuri);
03394          ast_http_uri_link(&manageruri);
03395          ast_http_uri_link(&managerxmluri);
03396          webregged = 1;
03397       }
03398    } else {
03399       if (webregged) {
03400          ast_http_uri_unlink(&rawmanuri);
03401          ast_http_uri_unlink(&manageruri);
03402          ast_http_uri_unlink(&managerxmluri);
03403          webregged = 0;
03404       }
03405    }
03406 
03407    if (newhttptimeout > 0)
03408       httptimeout = newhttptimeout;
03409 
03410    /* If not enabled, do nothing */
03411    if (!manager_enabled)
03412       return 0;
03413 
03414    if (asock < 0) {
03415       asock = socket(AF_INET, SOCK_STREAM, 0);
03416       if (asock < 0) {
03417          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
03418          return -1;
03419       }
03420       setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
03421       if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
03422          ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
03423          close(asock);
03424          asock = -1;
03425          return -1;
03426       }
03427       if (listen(asock, 2)) {
03428          ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
03429          close(asock);
03430          asock = -1;
03431          return -1;
03432       }
03433       flags = fcntl(asock, F_GETFL);
03434       fcntl(asock, F_SETFL, flags | O_NONBLOCK);
03435       if (option_verbose)
03436          ast_verbose("Asterisk Management interface listening on port %d\n", portno);
03437       ast_pthread_create_background(&t, NULL, accept_thread, NULL);
03438    }
03439    return 0;
03440 }

int reload_manager ( void   ) 

Definition at line 3442 of file manager.c.

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

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


Generated on Wed Oct 14 15:02:20 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7