Thu May 14 15:13:35 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 2815 of file manager.c.

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

02816 {
02817    int result = 0;
02818    struct mansession *s;
02819 
02820    AST_LIST_LOCK(&sessions);
02821    AST_LIST_TRAVERSE(&sessions, s, list) {
02822       ast_mutex_lock(&s->__lock);
02823       if ((s->managerid == ident) && (s->readperm & perm)) {
02824          result = 1;
02825          ast_mutex_unlock(&s->__lock);
02826          break;
02827       }
02828       ast_mutex_unlock(&s->__lock);
02829    }
02830    AST_LIST_UNLOCK(&sessions);
02831    return result;
02832 }

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

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

02835 {
02836    int result = 0;
02837    struct mansession *s;
02838 
02839    AST_LIST_LOCK(&sessions);
02840    AST_LIST_TRAVERSE(&sessions, s, list) {
02841       ast_mutex_lock(&s->__lock);
02842       if ((s->managerid == ident) && (s->writeperm & perm)) {
02843          result = 1;
02844          ast_mutex_unlock(&s->__lock);
02845          break;
02846       }
02847       ast_mutex_unlock(&s->__lock);
02848    }
02849    AST_LIST_UNLOCK(&sessions);
02850    return result;
02851 }

int init_manager ( void   ) 

Called by Asterisk initialization

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

03054 {
03055    struct ast_config *cfg = NULL, *ucfg = NULL;
03056    const char *val;
03057    char *cat = NULL;
03058    int oldportno = portno;
03059    static struct sockaddr_in ba;
03060    int x = 1;
03061    int flags;
03062    int newhttptimeout = 60;
03063    struct ast_manager_user *user = NULL;
03064 
03065    if (!registered) {
03066       /* Register default actions */
03067       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
03068       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
03069       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
03070       ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
03071       ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
03072       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
03073       ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
03074       ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
03075       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
03076       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
03077       ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer );
03078       ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
03079       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
03080       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
03081       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
03082       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
03083       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
03084       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
03085       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
03086       ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
03087       ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
03088       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
03089 
03090       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
03091       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
03092       registered = 1;
03093       /* Append placeholder event so master_eventq never runs dry */
03094       append_event("Event: Placeholder\r\n\r\n", 0);
03095    }
03096    portno = DEFAULT_MANAGER_PORT;
03097    displayconnects = 1;
03098    cfg = ast_config_load("manager.conf");
03099    if (!cfg) {
03100       ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
03101       return 0;
03102    }
03103    if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) {
03104       manager_enabled = ast_true(val);
03105    }
03106    if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) {
03107       block_sockets = ast_true(val);
03108    }
03109    if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) {
03110       webmanager_enabled = ast_true(val);
03111    }
03112    if ((val = ast_variable_retrieve(cfg, "general", "port"))) {
03113       if (sscanf(val, "%d", &portno) != 1) {
03114          ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
03115          portno = DEFAULT_MANAGER_PORT;
03116       }
03117    }
03118    if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) {
03119       displayconnects = ast_true(val);
03120    }
03121    if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) {
03122       timestampevents = ast_true(val);
03123    }
03124    if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) {
03125       newhttptimeout = atoi(val);
03126    }
03127 
03128    memset(&ba, 0, sizeof(ba));
03129    ba.sin_family = AF_INET;
03130    ba.sin_port = htons(portno);
03131 
03132    if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
03133       if (!inet_aton(val, &ba.sin_addr)) { 
03134          ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03135          memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
03136       }
03137    }
03138    
03139 
03140    if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) {
03141 #if 0
03142       /* Can't be done yet */
03143       close(asock);
03144       asock = -1;
03145 #else
03146       ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
03147 #endif
03148    }
03149 
03150    AST_LIST_LOCK(&users);
03151 
03152    if ((ucfg = ast_config_load("users.conf"))) {
03153       while ((cat = ast_category_browse(ucfg, cat))) {
03154          int hasmanager = 0;
03155          struct ast_variable *var = NULL;
03156 
03157          if (!strcasecmp(cat, "general")) {
03158             continue;
03159          }
03160 
03161          if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) {
03162             continue;
03163          }
03164 
03165          /* Look for an existing entry, if none found - create one and add it to the list */
03166          if (!(user = ast_get_manager_by_name_locked(cat))) {
03167             if (!(user = ast_calloc(1, sizeof(*user)))) {
03168                break;
03169             }
03170             /* Copy name over */
03171             ast_copy_string(user->username, cat, sizeof(user->username));
03172             /* Insert into list */
03173             AST_LIST_INSERT_TAIL(&users, user, list);
03174          }
03175 
03176          /* Make sure we keep this user and don't destroy it during cleanup */
03177          user->keep = 1;
03178 
03179          for (var = ast_variable_browse(ucfg, cat); var; var = var->next) {
03180             if (!strcasecmp(var->name, "secret")) {
03181                if (user->secret) {
03182                   free(user->secret);
03183                }
03184                user->secret = ast_strdup(var->value);
03185             } else if (!strcasecmp(var->name, "deny") ) {
03186                if (user->deny) {
03187                   free(user->deny);
03188                }
03189                user->deny = ast_strdup(var->value);
03190             } else if (!strcasecmp(var->name, "permit") ) {
03191                if (user->permit) {
03192                   free(user->permit);
03193                }
03194                user->permit = ast_strdup(var->value);
03195             } else if (!strcasecmp(var->name, "read") ) {
03196                if (user->read) {
03197                   free(user->read);
03198                }
03199                user->read = ast_strdup(var->value);
03200             } else if (!strcasecmp(var->name, "write") ) {
03201                if (user->write) {
03202                   free(user->write);
03203                }
03204                user->write = ast_strdup(var->value);
03205             } else if (!strcasecmp(var->name, "displayconnects") ) {
03206                user->displayconnects = ast_true(var->value);
03207             } else if (!strcasecmp(var->name, "hasmanager")) {
03208                /* already handled */
03209             } else {
03210                ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name);
03211             }
03212          }
03213       }
03214       ast_config_destroy(ucfg);
03215    }
03216 
03217    while ((cat = ast_category_browse(cfg, cat))) {
03218       struct ast_variable *var = NULL;
03219 
03220       if (!strcasecmp(cat, "general"))
03221          continue;
03222 
03223       /* Look for an existing entry, if none found - create one and add it to the list */
03224       if (!(user = ast_get_manager_by_name_locked(cat))) {
03225          if (!(user = ast_calloc(1, sizeof(*user))))
03226             break;
03227          /* Copy name over */
03228          ast_copy_string(user->username, cat, sizeof(user->username));
03229          /* Insert into list */
03230          AST_LIST_INSERT_TAIL(&users, user, list);
03231       }
03232 
03233       /* Make sure we keep this user and don't destroy it during cleanup */
03234       user->keep = 1;
03235 
03236       var = ast_variable_browse(cfg, cat);
03237       while (var) {
03238          if (!strcasecmp(var->name, "secret")) {
03239             if (user->secret)
03240                free(user->secret);
03241             user->secret = ast_strdup(var->value);
03242          } else if (!strcasecmp(var->name, "deny") ) {
03243             if (user->deny)
03244                free(user->deny);
03245             user->deny = ast_strdup(var->value);
03246          } else if (!strcasecmp(var->name, "permit") ) {
03247             if (user->permit)
03248                free(user->permit);
03249             user->permit = ast_strdup(var->value);
03250          }  else if (!strcasecmp(var->name, "read") ) {
03251             if (user->read)
03252                free(user->read);
03253             user->read = ast_strdup(var->value);
03254          }  else if (!strcasecmp(var->name, "write") ) {
03255             if (user->write)
03256                free(user->write);
03257             user->write = ast_strdup(var->value);
03258          }  else if (!strcasecmp(var->name, "displayconnects") )
03259             user->displayconnects = ast_true(var->value);
03260          else
03261             ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03262          var = var->next;
03263       }
03264    }
03265 
03266    /* Perform cleanup - essentially prune out old users that no longer exist */
03267    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03268       if (user->keep) {
03269          user->keep = 0;
03270          continue;
03271       }
03272       /* We do not need to keep this user so take them out of the list */
03273       AST_LIST_REMOVE_CURRENT(&users, list);
03274       /* Free their memory now */
03275       if (user->secret)
03276          free(user->secret);
03277       if (user->deny)
03278          free(user->deny);
03279       if (user->permit)
03280          free(user->permit);
03281       if (user->read)
03282          free(user->read);
03283       if (user->write)
03284          free(user->write);
03285       free(user);
03286    }
03287    AST_LIST_TRAVERSE_SAFE_END
03288 
03289    AST_LIST_UNLOCK(&users);
03290 
03291    ast_config_destroy(cfg);
03292    
03293    if (webmanager_enabled && manager_enabled) {
03294       if (!webregged) {
03295          ast_http_uri_link(&rawmanuri);
03296          ast_http_uri_link(&manageruri);
03297          ast_http_uri_link(&managerxmluri);
03298          webregged = 1;
03299       }
03300    } else {
03301       if (webregged) {
03302          ast_http_uri_unlink(&rawmanuri);
03303          ast_http_uri_unlink(&manageruri);
03304          ast_http_uri_unlink(&managerxmluri);
03305          webregged = 0;
03306       }
03307    }
03308 
03309    if (newhttptimeout > 0)
03310       httptimeout = newhttptimeout;
03311 
03312    /* If not enabled, do nothing */
03313    if (!manager_enabled)
03314       return 0;
03315 
03316    if (asock < 0) {
03317       asock = socket(AF_INET, SOCK_STREAM, 0);
03318       if (asock < 0) {
03319          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
03320          return -1;
03321       }
03322       setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
03323       if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
03324          ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
03325          close(asock);
03326          asock = -1;
03327          return -1;
03328       }
03329       if (listen(asock, 2)) {
03330          ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
03331          close(asock);
03332          asock = -1;
03333          return -1;
03334       }
03335       flags = fcntl(asock, F_GETFL);
03336       fcntl(asock, F_SETFL, flags | O_NONBLOCK);
03337       if (option_verbose)
03338          ast_verbose("Asterisk Management interface listening on port %d\n", portno);
03339       ast_pthread_create_background(&t, NULL, accept_thread, NULL);
03340    }
03341    return 0;
03342 }

int reload_manager ( void   ) 

Definition at line 3344 of file manager.c.

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

03345 {
03346    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03347    return init_manager();
03348 }


Generated on Thu May 14 15:13:35 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7