Thu Feb 5 16:26:17 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 action_userevent(), aji_log_hook(), init_manager(), and userevent_exec().

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

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

02801 {
02802    int result = 0;
02803    struct mansession *s;
02804 
02805    AST_LIST_LOCK(&sessions);
02806    AST_LIST_TRAVERSE(&sessions, s, list) {
02807       ast_mutex_lock(&s->__lock);
02808       if ((s->managerid == ident) && (s->readperm & perm)) {
02809          result = 1;
02810          ast_mutex_unlock(&s->__lock);
02811          break;
02812       }
02813       ast_mutex_unlock(&s->__lock);
02814    }
02815    AST_LIST_UNLOCK(&sessions);
02816    return result;
02817 }

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

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

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

int init_manager ( void   ) 

Called by Asterisk initialization

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

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

int reload_manager ( void   ) 

Definition at line 3329 of file manager.c.

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

03330 {
03331    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03332    return init_manager();
03333 }


Generated on Thu Feb 5 16:26:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7