Sun Dec 18 20:55:52 2011

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"

Include dependency graph for manager.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  manager_action
struct  message

Defines

#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_EXTENSIONSTATUS   (1 << 8)
#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

void __attribute__ ((format(printf, 2, 3))) astman_append(struct mansession *s
int __attribute__ ((format(printf, 3, 4))) manager_event(int category
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)
int const char const char
const char * 
astman_get_header (const struct message *m, char *var)
struct 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.
void const char int init_manager (void)
int reload_manager (void)

Variables

int const char const char * contents
int const char * event
void const char * fmt


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 ast_manager_register ( a,
b,
c,
 )     ast_manager_register2(a, b, c, d, NULL)

Definition at line 86 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(), and generic_http_callback().

#define DEFAULT_MANAGER_PORT   5038

Definition at line 48 of file manager.h.

Referenced by init_manager().

#define EVENT_FLAG_AGENT   (1 << 5)

#define EVENT_FLAG_CALL   (1 << 1)

#define EVENT_FLAG_COMMAND   (1 << 4)

Definition at line 54 of file manager.h.

Referenced by init_manager(), and load_module().

#define EVENT_FLAG_CONFIG   (1 << 7)

Definition at line 57 of file manager.h.

Referenced by init_manager().

#define EVENT_FLAG_EXTENSIONSTATUS   (1 << 8)

Definition at line 58 of file manager.h.

Referenced by manager_state_cb().

#define EVENT_FLAG_LOG   (1 << 2)

Definition at line 52 of file manager.h.

#define EVENT_FLAG_SYSTEM   (1 << 0)

#define EVENT_FLAG_USER   (1 << 6)

Definition at line 56 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 53 of file manager.h.


Function Documentation

void __attribute__ ( (format(printf, 2, 3))   ) 

int __attribute__ ( (format(printf, 3, 4))   ) 

External routines may send asterisk manager events this way

Parameters:
category Event category, matches manager authorization
event Event name
contents Contents of event

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

References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, mansession::readperm, and s.

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

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

References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, s, and mansession::writeperm.

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

void const char int init_manager ( void   ) 

Called by Asterisk initialization

Type Constraints

Definition at line 3051 of file manager.c.

References accept_thread(), action_command(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_message(), action_originate(), action_ping(), action_redirect(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), append_event(), ast_calloc, ast_category_browse(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_extension_state_add(), ast_get_manager_by_name_locked(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_manager_register, ast_manager_register2(), ast_pthread_create_background, ast_strdup, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), DEFAULT_MANAGER_PORT, ast_manager_user::deny, ast_manager_user::displayconnects, errno, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_USER, ast_channel::flags, free, ast_manager_user::keep, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_state_cb(), ast_variable::name, ast_variable::next, option_verbose, ast_manager_user::permit, ast_manager_user::read, ast_manager_user::secret, ast_manager_user::username, users, ast_variable::value, var, and ast_manager_user::write.

Referenced by main(), and reload_manager().

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

int reload_manager ( void   ) 

Definition at line 3371 of file manager.c.

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

03372 {
03373    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03374    return init_manager();
03375 }


Variable Documentation

int const char const char* contents

Definition at line 130 of file manager.h.

int const char* event

void const char* fmt


Generated on Sun Dec 18 20:55:52 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6