Fri Nov 12 12:11:17 2010

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

struct  actions
 list of actions registered More...
struct  all_events
struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  manager_hooks
 list of hooks registered More...
struct  mansession
struct  mansession_session
struct  permalias
struct  sessions
struct  users
 list of users found in the config file More...

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define GET_HEADER_FIRST_MATCH   0
#define GET_HEADER_LAST_MATCH   1
#define GET_HEADER_SKIP_EMPTY   2
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MSG_MOREDATA   ((char *)astman_send_response)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
#define NEW_EVENT(m)   (AST_LIST_NEXT(m->session->last_ev, eq_next))

Enumerations

enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}

Functions

static const char * __astman_get_header (const struct message *m, char *var, int mode)
static void __init_astman_append_buf (void)
 thread local buffer for astman_append
static void __init_manager_event_buf (void)
static void __init_userevent_buf (void)
int __manager_event (int category, const char *event, const char *file, int line, const char *func, const char *fmt,...)
 manager_event: Send AMI event to client
static int action_atxfer (struct mansession *s, const struct message *m)
static int action_challenge (struct mansession *s, const struct message *m)
static int action_command (struct mansession *s, const struct message *m)
 Manager command "command" - execute CLI command.
static int action_coresettings (struct mansession *s, const struct message *m)
 Show PBX core settings information.
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
static int action_createconfig (struct mansession *s, const struct message *m)
static int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
static int action_getconfig (struct mansession *s, const struct message *m)
static int action_getconfigjson (struct mansession *s, const struct message *m)
static int action_getvar (struct mansession *s, const struct message *m)
static int action_hangup (struct mansession *s, const struct message *m)
static int action_listcategories (struct mansession *s, const struct message *m)
static int action_listcommands (struct mansession *s, const struct message *m)
static int action_login (struct mansession *s, const struct message *m)
static int action_logoff (struct mansession *s, const struct message *m)
static int action_mailboxcount (struct mansession *s, const struct message *m)
static int action_mailboxstatus (struct mansession *s, const struct message *m)
static int action_originate (struct mansession *s, const struct message *m)
static int action_ping (struct mansession *s, const struct message *m)
static int action_redirect (struct mansession *s, const struct message *m)
 action_redirect: The redirect manager command
static int action_reload (struct mansession *s, const struct message *m)
 Send a reload event.
static int action_sendtext (struct mansession *s, const struct message *m)
static int action_setvar (struct mansession *s, const struct message *m)
static int action_status (struct mansession *s, const struct message *m)
 Manager "status" command to show channels.
static int action_timeout (struct mansession *s, const struct message *m)
static int action_updateconfig (struct mansession *s, const struct message *m)
static int action_userevent (struct mansession *s, const struct message *m)
static int action_waitevent (struct mansession *s, const struct message *m)
static int append_event (const char *str, int category)
static int ast_instring (const char *bigstr, const char *smallstr, const char delim)
int ast_manager_register2 (const char *action, int auth, 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
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired.
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 Unregister a registered manager command.
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
 Get header from mananger transaction.
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
static void astman_start_ack (struct mansession *s, const struct message *m)
static int authenticate (struct mansession *s, const struct message *m)
static char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static int check_blacklist (const char *cmd)
int check_manager_enabled ()
 Event list management functions. We assume that the event list always has at least one element, and the delete code will not remove the last entry even if the.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled ()
 Check if AMI/HTTP is enabled.
static void destroy_session (struct mansession_session *session)
static int do_message (struct mansession *s)
static void * fast_originate (void *data)
static void free_session (struct mansession_session *session)
static int get_input (struct mansession *s, char *output)
static struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
static void json_escape (char *out, const char *in)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static int manager_modulecheck (struct mansession *s, const struct message *m)
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (char *context, char *exten, int state, void *data)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
static void purge_events (void)
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static void ref_event (struct eventqent *e)
static int send_string (struct mansession *s, char *string)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static struct eventqentunref_event (struct eventqent *e)

Variables

static int allowmultiplelogin = 1
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
static int block_sockets
static struct ast_cli_entry cli_manager []
struct {
   char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static int displayconnects = 1
static int httptimeout = 60
static int manager_debug
static int manager_enabled = 0
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
static char mandescr_atxfer []
static char mandescr_command []
static char mandescr_coresettings []
static char mandescr_coreshowchannels []
static char mandescr_corestatus []
static char mandescr_createconfig []
static char mandescr_events []
static char mandescr_extensionstate []
static char mandescr_getconfig []
static char mandescr_getconfigjson []
static char mandescr_getvar []
static char mandescr_hangup []
static char mandescr_listcategories []
static char mandescr_listcommands []
static char mandescr_logoff []
static char mandescr_mailboxcount []
static char mandescr_mailboxstatus []
 Help text for manager command mailboxstatus.
static char mandescr_modulecheck []
static char mandescr_moduleload []
static char mandescr_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_reload []
static char mandescr_sendtext []
static char mandescr_setvar []
static char mandescr_status []
static char mandescr_timeout []
static char mandescr_updateconfig []
static char mandescr_userevent []
static char mandescr_waitevent []
 Manager WAITEVENT.
static int num_sessions
static struct permalias perms []
static int timestampevents
static struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
static int webmanager_enabled = 0

Detailed Description

callback to display queues status in manager

callback to display list of locally configured nodes


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 964 of file manager.c.

Referenced by astman_append().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 867 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 868 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 869 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 3297 of file manager.c.

Referenced by __manager_event().

#define MAX_BLACKLIST_CMD_LEN   2

Descriptor for a manager session, either on the AMI socket or over HTTP.

Note:
AMI session have managerid == 0; the entry is created upon a connect, and destroyed with the socket. HTTP sessions have managerid != 0, the value is used as a search key to lookup sessions (using the mansession_id cookie).

Definition at line 143 of file manager.c.

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.

Note:
NOTE: XXX this comment is unclear and possibly wrong. Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER hold the session lock _or_ be running in an action callback (in which case s->session->busy will be non-zero). In either of these cases, there is no need to lock-protect the session's fd, since no other output will be sent (events will be queued), and no input will be read until either the current action finishes or get_input() obtains the session lock.

Use the explicit constant MSG_MOREDATA to remove the empty line. XXX MSG_MOREDATA should go to a header file.

Definition at line 1004 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().

#define NEW_EVENT (  )     (AST_LIST_NEXT(m->session->last_ev, eq_next))

Definition at line 224 of file manager.c.

Referenced by action_waitevent(), and process_events().


Enumeration Type Documentation

enum error_type

Doxygen group

Enumerator:
UNKNOWN_ACTION 
UNKNOWN_CATEGORY 
UNSPECIFIED_CATEGORY 
UNSPECIFIED_ARGUMENT 
FAILURE_ALLOCATION 
FAILURE_NEWCAT 
FAILURE_DELCAT 
FAILURE_EMPTYCAT 
FAILURE_UPDATE 
FAILURE_DELETE 
FAILURE_APPEND 

Definition at line 78 of file manager.c.


Function Documentation

static const char* __astman_get_header ( const struct message m,
char *  var,
int  mode 
) [static]

Definition at line 870 of file manager.c.

References ast_strlen_zero(), GET_HEADER_LAST_MATCH, GET_HEADER_SKIP_EMPTY, message::hdrcount, and message::headers.

Referenced by astman_get_header(), and process_message().

00871 {
00872    int x, l = strlen(var);
00873    const char *result = "";
00874 
00875    for (x = 0; x < m->hdrcount; x++) {
00876       const char *h = m->headers[x];
00877       if (!strncasecmp(var, h, l) && h[l] == ':' && h[l+1] == ' ') {
00878          const char *value = h + l + 2;
00879          /* found a potential candidate */
00880          if (mode & GET_HEADER_SKIP_EMPTY && ast_strlen_zero(value))
00881             continue;   /* not interesting */
00882          if (mode & GET_HEADER_LAST_MATCH)
00883             result = value;   /* record the last match so far */
00884          else
00885             return value;
00886       }
00887    }
00888 
00889    return "";
00890 }

static void __init_astman_append_buf ( void   )  [static]

thread local buffer for astman_append

Note:
This can not be defined within the astman_append() function because it declares a couple of functions that get used to initialize the thread local storage key.

Definition at line 960 of file manager.c.

00970 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 3296 of file manager.c.

03299 : Send AMI event to client */

static void __init_userevent_buf ( void   )  [static]

Definition at line 961 of file manager.c.

00970 {

int __manager_event ( int  category,
const char *  event,
const char *  file,
int  line,
const char *  func,
const char *  fmt,
  ... 
)

manager_event: Send AMI event to client

Definition at line 3300 of file manager.c.

References mansession_session::__lock, append_event(), ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_append_va(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_tvnow(), authority_to_str(), buf, manager_custom_hook::helper, manager_event_buf, MANAGER_EVENT_BUF_INITSIZE, mansession_session::pending_event, eventqent::seq, and mansession_session::waiting_thread.

03302 {
03303    struct mansession_session *session;
03304    struct manager_custom_hook *hook;
03305    struct ast_str *auth = ast_str_alloca(80);
03306    const char *cat_str;
03307    va_list ap;
03308    struct timeval now;
03309    struct ast_str *buf;
03310 
03311    /* Abort if there are neither any manager sessions nor hooks */
03312    if (!num_sessions && AST_RWLIST_EMPTY(&manager_hooks))
03313       return 0;
03314 
03315    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE)))
03316       return -1;
03317 
03318    cat_str = authority_to_str(category, &auth);
03319    ast_str_set(&buf, 0,
03320          "Event: %s\r\nPrivilege: %s\r\n",
03321           event, cat_str);
03322 
03323    if (timestampevents) {
03324       now = ast_tvnow();
03325       ast_str_append(&buf, 0,
03326             "Timestamp: %ld.%06lu\r\n",
03327              (long)now.tv_sec, (unsigned long) now.tv_usec);
03328    }
03329    if (manager_debug) {
03330       static int seq;
03331       ast_str_append(&buf, 0,
03332             "SequenceNumber: %d\r\n",
03333              ast_atomic_fetchadd_int(&seq, 1));
03334       ast_str_append(&buf, 0,
03335             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
03336    }
03337 
03338    va_start(ap, fmt);
03339    ast_str_append_va(&buf, 0, fmt, ap);
03340    va_end(ap);
03341 
03342    ast_str_append(&buf, 0, "\r\n");
03343 
03344    append_event(ast_str_buffer(buf), category);
03345 
03346    if (num_sessions) {
03347       /* Wake up any sleeping sessions */
03348       AST_LIST_LOCK(&sessions);
03349       AST_LIST_TRAVERSE(&sessions, session, list) {
03350          ast_mutex_lock(&session->__lock);
03351          if (session->waiting_thread != AST_PTHREADT_NULL)
03352             pthread_kill(session->waiting_thread, SIGURG);
03353          else
03354             /* We have an event to process, but the mansession is
03355              * not waiting for it. We still need to indicate that there
03356              * is an event waiting so that get_input processes the pending
03357              * event instead of polling.
03358              */
03359             session->pending_event = 1;
03360          ast_mutex_unlock(&session->__lock);
03361       }
03362       AST_LIST_UNLOCK(&sessions);
03363    }
03364 
03365    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
03366       AST_RWLIST_RDLOCK(&manager_hooks);
03367       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
03368          hook->helper(category, event, ast_str_buffer(buf));
03369       }
03370       AST_RWLIST_UNLOCK(&manager_hooks);
03371    }
03372 
03373    return 0;
03374 }

static int action_atxfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 2168 of file manager.c.

References ast_channel_unlock, ast_find_call_feature(), AST_FRAME_DTMF, ast_get_channel_by_name_locked(), ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), chan, context, ast_call_feature::exten, exten, name, and pbx_builtin_setvar_helper().

Referenced by __init_manager().

02169 {
02170    const char *name = astman_get_header(m, "Channel");
02171    const char *exten = astman_get_header(m, "Exten");
02172    const char *context = astman_get_header(m, "Context");
02173    struct ast_channel *chan = NULL;
02174    struct ast_call_feature *atxfer_feature = NULL;
02175    char *feature_code = NULL;
02176 
02177    if (ast_strlen_zero(name)) { 
02178       astman_send_error(s, m, "No channel specified");
02179       return 0;
02180    }
02181    if (ast_strlen_zero(exten)) {
02182       astman_send_error(s, m, "No extension specified");
02183       return 0;
02184    }
02185 
02186    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
02187       astman_send_error(s, m, "No attended transfer feature found");
02188       return 0;
02189    }
02190 
02191    if (!(chan = ast_get_channel_by_name_locked(name))) {
02192       astman_send_error(s, m, "Channel specified does not exist");
02193       return 0;
02194    }
02195 
02196    if (!ast_strlen_zero(context)) {
02197       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
02198    }
02199 
02200    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
02201       struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
02202       ast_queue_frame(chan, &f);
02203    }
02204 
02205    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
02206       struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
02207       ast_queue_frame(chan, &f);
02208    }
02209 
02210    astman_send_ack(s, m, "Atxfer successfully queued");
02211    ast_channel_unlock(chan);
02212 
02213    return 0;
02214 }

static int action_challenge ( struct mansession s,
const struct message m 
) [static]

Definition at line 1755 of file manager.c.

References mansession_session::__lock, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), mansession_session::challenge, and mansession::session.

Referenced by __init_manager().

01756 {
01757    const char *authtype = astman_get_header(m, "AuthType");
01758 
01759    if (!strcasecmp(authtype, "MD5")) {
01760       if (ast_strlen_zero(s->session->challenge))
01761          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
01762       ast_mutex_lock(&s->session->__lock);
01763       astman_start_ack(s, m);
01764       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
01765       ast_mutex_unlock(&s->session->__lock);
01766    } else {
01767       astman_send_error(s, m, "Must specify AuthType");
01768    }
01769    return 0;
01770 }

static int action_command ( struct mansession s,
const struct message m 
) [static]

Manager command "command" - execute CLI command.

Definition at line 2258 of file manager.c.

References ast_calloc, ast_cli_command, ast_free, ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), buf, check_blacklist(), errno, LOG_WARNING, S_OR, and term_strip().

Referenced by __init_manager().

02259 {
02260    const char *cmd = astman_get_header(m, "Command");
02261    const char *id = astman_get_header(m, "ActionID");
02262    char *buf, *final_buf;
02263    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
02264    int fd;
02265    off_t l;
02266 
02267    if (ast_strlen_zero(cmd)) {
02268       astman_send_error(s, m, "No command provided");
02269       return 0;
02270    }
02271 
02272    if (check_blacklist(cmd)) {
02273       astman_send_error(s, m, "Command blacklisted");
02274       return 0;
02275    }
02276 
02277    fd = mkstemp(template);
02278 
02279    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
02280    if (!ast_strlen_zero(id))
02281       astman_append(s, "ActionID: %s\r\n", id);
02282    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
02283    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
02284    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
02285 
02286    /* This has a potential to overflow the stack.  Hence, use the heap. */
02287    buf = ast_calloc(1, l + 1);
02288    final_buf = ast_calloc(1, l + 1);
02289    if (buf) {
02290       lseek(fd, 0, SEEK_SET);
02291       if (read(fd, buf, l) < 0) {
02292          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
02293       }
02294       buf[l] = '\0';
02295       if (final_buf) {
02296          term_strip(final_buf, buf, l);
02297          final_buf[l] = '\0';
02298       }
02299       astman_append(s, "%s", S_OR(final_buf, buf));
02300       ast_free(buf);
02301    }
02302    close(fd);
02303    unlink(template);
02304    astman_append(s, "--END COMMAND--\r\n\r\n");
02305    if (final_buf)
02306       ast_free(final_buf);
02307    return 0;
02308 }

static int action_coresettings ( struct mansession s,
const struct message m 
) [static]

Show PBX core settings information.

Definition at line 2709 of file manager.c.

References AMI_VERSION, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_realtime_enabled(), ast_strlen_zero(), astman_append(), astman_get_header(), check_cdr_enabled(), check_webmanager_enabled(), option_maxcalls, option_maxfiles, and option_maxload.

Referenced by __init_manager().

02710 {
02711    const char *actionid = astman_get_header(m, "ActionID");
02712    char idText[150];
02713 
02714    if (!ast_strlen_zero(actionid))
02715       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
02716    else
02717       idText[0] = '\0';
02718 
02719    astman_append(s, "Response: Success\r\n"
02720          "%s"
02721          "AMIversion: %s\r\n"
02722          "AsteriskVersion: %s\r\n"
02723          "SystemName: %s\r\n"
02724          "CoreMaxCalls: %d\r\n"
02725          "CoreMaxLoadAvg: %f\r\n"
02726          "CoreRunUser: %s\r\n"
02727          "CoreRunGroup: %s\r\n"
02728          "CoreMaxFilehandles: %d\r\n" 
02729          "CoreRealTimeEnabled: %s\r\n"
02730          "CoreCDRenabled: %s\r\n"
02731          "CoreHTTPenabled: %s\r\n"
02732          "\r\n",
02733          idText,
02734          AMI_VERSION,
02735          ast_get_version(), 
02736          ast_config_AST_SYSTEM_NAME,
02737          option_maxcalls,
02738          option_maxload,
02739          ast_config_AST_RUN_USER,
02740          ast_config_AST_RUN_GROUP,
02741          option_maxfiles,
02742          ast_realtime_enabled() ? "Yes" : "No",
02743          check_cdr_enabled() ? "Yes" : "No",
02744          check_webmanager_enabled() ? "Yes" : "No"
02745          );
02746    return 0;
02747 }

static int action_coreshowchannels ( struct mansession s,
const struct message m 
) [static]

Manager command "CoreShowChannels" - List currently defined channels and some information about them.

Definition at line 2814 of file manager.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::appl, ast_bridged_channel(), ast_channel_unlock, ast_channel_walk_locked(), ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_listack(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::data, ast_channel::exten, ast_channel::name, ast_channel::priority, S_OR, ast_cdr::start, and ast_channel::uniqueid.

Referenced by __init_manager().

02815 {
02816    const char *actionid = astman_get_header(m, "ActionID");
02817    char idText[256];
02818    struct ast_channel *c = NULL;
02819    int numchans = 0;
02820    int duration, durh, durm, durs;
02821 
02822    if (!ast_strlen_zero(actionid))
02823       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
02824    else
02825       idText[0] = '\0';
02826 
02827    astman_send_listack(s, m, "Channels will follow", "start"); 
02828 
02829    while ((c = ast_channel_walk_locked(c)) != NULL) {
02830       struct ast_channel *bc = ast_bridged_channel(c);
02831       char durbuf[10] = "";
02832 
02833       if (c->cdr && !ast_tvzero(c->cdr->start)) {
02834          duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
02835          durh = duration / 3600;
02836          durm = (duration % 3600) / 60;
02837          durs = duration % 60;
02838          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
02839       }
02840 
02841       astman_append(s,
02842          "Event: CoreShowChannel\r\n"
02843          "%s"
02844          "Channel: %s\r\n"
02845          "UniqueID: %s\r\n"
02846          "Context: %s\r\n"
02847          "Extension: %s\r\n"
02848          "Priority: %d\r\n"
02849          "ChannelState: %d\r\n"
02850          "ChannelStateDesc: %s\r\n"
02851          "Application: %s\r\n"
02852          "ApplicationData: %s\r\n"
02853          "CallerIDnum: %s\r\n"
02854          "Duration: %s\r\n"
02855          "AccountCode: %s\r\n"
02856          "BridgedChannel: %s\r\n"
02857          "BridgedUniqueID: %s\r\n"
02858          "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
02859          ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
02860          S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
02861       ast_channel_unlock(c);
02862       numchans++;
02863    }
02864 
02865    astman_append(s,
02866       "Event: CoreShowChannelsComplete\r\n"
02867       "EventList: Complete\r\n"
02868       "ListItems: %d\r\n"
02869       "%s"
02870       "\r\n", numchans, idText);
02871 
02872    return 0;
02873 }

static int action_corestatus ( struct mansession s,
const struct message m 
) [static]

Show PBX core status information.

Definition at line 2755 of file manager.c.

References ast_active_channels(), ast_lastreloadtime, ast_localtime(), ast_startuptime, ast_strftime(), ast_strlen_zero(), astman_append(), and astman_get_header().

Referenced by __init_manager().

02756 {
02757    const char *actionid = astman_get_header(m, "ActionID");
02758    char idText[150];
02759    char startuptime[150];
02760    char reloadtime[150];
02761    struct ast_tm tm;
02762 
02763    if (!ast_strlen_zero(actionid))
02764       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
02765    else
02766       idText[0] = '\0';
02767 
02768    ast_localtime(&ast_startuptime, &tm, NULL);
02769    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
02770    ast_localtime(&ast_lastreloadtime, &tm, NULL);
02771    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
02772 
02773    astman_append(s, "Response: Success\r\n"
02774          "%s"
02775          "CoreStartupTime: %s\r\n"
02776          "CoreReloadTime: %s\r\n"
02777          "CoreCurrentCalls: %d\r\n"
02778          "\r\n",
02779          idText,
02780          startuptime,
02781          reloadtime,
02782          ast_active_channels()
02783          );
02784    return 0;
02785 }

static int action_createconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 1565 of file manager.c.

References ast_config_AST_CONFIG_DIR, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), astman_get_header(), astman_send_ack(), astman_send_error(), and errno.

Referenced by __init_manager().

01566 {
01567    int fd;
01568    const char *fn = astman_get_header(m, "Filename");
01569    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
01570    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
01571    ast_str_append(&filepath, 0, "%s", fn);
01572 
01573    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
01574       close(fd);
01575       astman_send_ack(s, m, "New configuration file created successfully");
01576    } else {
01577       astman_send_error(s, m, strerror(errno));
01578    }
01579 
01580    return 0;
01581 }

static int action_events ( struct mansession s,
const struct message m 
) [static]

Definition at line 1715 of file manager.c.

References astman_append(), astman_get_header(), and set_eventmask().

Referenced by __init_manager().

01716 {
01717    const char *mask = astman_get_header(m, "EventMask");
01718    int res;
01719 
01720    res = set_eventmask(s, mask);
01721    if (res > 0)
01722       astman_append(s, "Response: Success\r\n"
01723              "Events: On\r\n\r\n");
01724    else if (res == 0)
01725       astman_append(s, "Response: Success\r\n"
01726              "Events: Off\r\n\r\n");
01727    return 0;
01728 }

static int action_extensionstate ( struct mansession s,
const struct message m 
) [static]

Definition at line 2590 of file manager.c.

References ast_extension_state(), ast_get_hint(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), context, exten, and status.

Referenced by __init_manager().

02591 {
02592    const char *exten = astman_get_header(m, "Exten");
02593    const char *context = astman_get_header(m, "Context");
02594    char hint[256] = "";
02595    int status;
02596    if (ast_strlen_zero(exten)) {
02597       astman_send_error(s, m, "Extension not specified");
02598       return 0;
02599    }
02600    if (ast_strlen_zero(context))
02601       context = "default";
02602    status = ast_extension_state(NULL, context, exten);
02603    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
02604    astman_start_ack(s, m);
02605    astman_append(s,   "Message: Extension Status\r\n"
02606             "Exten: %s\r\n"
02607             "Context: %s\r\n"
02608             "Hint: %s\r\n"
02609             "Status: %d\r\n\r\n",
02610             exten, context, hint, status);
02611    return 0;
02612 }

static int action_getconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 1156 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

01157 {
01158    struct ast_config *cfg;
01159    const char *fn = astman_get_header(m, "Filename");
01160    const char *category = astman_get_header(m, "Category");
01161    int catcount = 0;
01162    int lineno = 0;
01163    char *cur_category = NULL;
01164    struct ast_variable *v;
01165    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
01166 
01167    if (ast_strlen_zero(fn)) {
01168       astman_send_error(s, m, "Filename not specified");
01169       return 0;
01170    }
01171    cfg = ast_config_load2(fn, "manager", config_flags);
01172    if (cfg == CONFIG_STATUS_FILEMISSING) {
01173       astman_send_error(s, m, "Config file not found");
01174       return 0;
01175    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01176       astman_send_error(s, m, "Config file has invalid format");
01177       return 0;
01178    }
01179 
01180    astman_start_ack(s, m);
01181    while ((cur_category = ast_category_browse(cfg, cur_category))) {
01182       if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
01183          lineno = 0;
01184          astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
01185          for (v = ast_variable_browse(cfg, cur_category); v; v = v->next)
01186             astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
01187          catcount++;
01188       }
01189    }
01190    if (!ast_strlen_zero(category) && catcount == 0) /* TODO: actually, a config with no categories doesn't even get loaded */
01191       astman_append(s, "No categories found\r\n");
01192    ast_config_destroy(cfg);
01193    astman_append(s, "\r\n");
01194 
01195    return 0;
01196 }

static int action_getconfigjson ( struct mansession s,
const struct message m 
) [static]

Definition at line 1257 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), buf, eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, json_escape(), ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

01258 {
01259    struct ast_config *cfg;
01260    const char *fn = astman_get_header(m, "Filename");
01261    char *category = NULL;
01262    struct ast_variable *v;
01263    int comma1 = 0;
01264    char *buf = NULL;
01265    unsigned int buf_len = 0;
01266    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
01267 
01268    if (ast_strlen_zero(fn)) {
01269       astman_send_error(s, m, "Filename not specified");
01270       return 0;
01271    }
01272 
01273    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
01274       astman_send_error(s, m, "Config file not found");
01275       return 0;
01276    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01277       astman_send_error(s, m, "Config file has invalid format");
01278       return 0;
01279    }
01280 
01281    buf_len = 512;
01282    buf = alloca(buf_len);
01283 
01284    astman_start_ack(s, m);
01285    astman_append(s, "JSON: {");
01286    while ((category = ast_category_browse(cfg, category))) {
01287       int comma2 = 0;
01288       if (buf_len < 2 * strlen(category) + 1) {
01289          buf_len *= 2;
01290          buf = alloca(buf_len);
01291       }
01292       json_escape(buf, category);
01293       astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf);
01294       if (!comma1)
01295          comma1 = 1;
01296       for (v = ast_variable_browse(cfg, category); v; v = v->next) {
01297          if (comma2)
01298             astman_append(s, ",");
01299          if (buf_len < 2 * strlen(v->name) + 1) {
01300             buf_len *= 2;
01301             buf = alloca(buf_len);
01302          }
01303          json_escape(buf, v->name);
01304          astman_append(s, "\"%s", buf);
01305          if (buf_len < 2 * strlen(v->value) + 1) {
01306             buf_len *= 2;
01307             buf = alloca(buf_len);
01308          }
01309          json_escape(buf, v->value);
01310          astman_append(s, "%s\"", buf);
01311          if (!comma2)
01312             comma2 = 1;
01313       }
01314       astman_append(s, "]");
01315    }
01316    astman_append(s, "}\r\n\r\n");
01317 
01318    ast_config_destroy(cfg);
01319 
01320    return 0;
01321 }

static int action_getvar ( struct mansession s,
const struct message m 
) [static]

Definition at line 1847 of file manager.c.

References ast_channel_alloc, ast_channel_free(), ast_channel_unlock, ast_func_read(), ast_get_channel_by_name_locked(), ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), LOG_ERROR, name, and pbx_retrieve_variable().

Referenced by __init_manager().

01848 {
01849    struct ast_channel *c = NULL;
01850    const char *name = astman_get_header(m, "Channel");
01851    const char *varname = astman_get_header(m, "Variable");
01852    char *varval;
01853    char workspace[1024] = "";
01854 
01855    if (ast_strlen_zero(varname)) {
01856       astman_send_error(s, m, "No variable specified");
01857       return 0;
01858    }
01859 
01860    if (!ast_strlen_zero(name)) {
01861       c = ast_get_channel_by_name_locked(name);
01862       if (!c) {
01863          astman_send_error(s, m, "No such channel");
01864          return 0;
01865       }
01866    }
01867 
01868    if (varname[strlen(varname) - 1] == ')') {
01869       if (!c) {
01870          c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/manager");
01871          if (c) {
01872             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
01873             ast_channel_free(c);
01874             c = NULL;
01875          } else
01876             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
01877       } else
01878          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
01879       varval = workspace;
01880    } else {
01881       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
01882    }
01883 
01884    if (c)
01885       ast_channel_unlock(c);
01886    astman_start_ack(s, m);
01887    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, varval);
01888 
01889    return 0;
01890 }

static int action_hangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 1777 of file manager.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.

Referenced by __init_manager().

01778 {
01779    struct ast_channel *c = NULL;
01780    const char *name = astman_get_header(m, "Channel");
01781    if (ast_strlen_zero(name)) {
01782       astman_send_error(s, m, "No channel specified");
01783       return 0;
01784    }
01785    c = ast_get_channel_by_name_locked(name);
01786    if (!c) {
01787       astman_send_error(s, m, "No such channel");
01788       return 0;
01789    }
01790    ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
01791    ast_channel_unlock(c);
01792    astman_send_ack(s, m, "Channel Hungup");
01793    return 0;
01794 }

static int action_listcategories ( struct mansession s,
const struct message m 
) [static]

Definition at line 1204 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, and CONFIG_STATUS_FILEINVALID.

Referenced by __init_manager().

01205 {
01206    struct ast_config *cfg;
01207    const char *fn = astman_get_header(m, "Filename");
01208    char *category = NULL;
01209    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
01210    int catcount = 0;
01211 
01212    if (ast_strlen_zero(fn)) {
01213       astman_send_error(s, m, "Filename not specified");
01214       return 0;
01215    }
01216    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
01217       astman_send_error(s, m, "Config file not found");
01218       return 0;
01219    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01220       astman_send_error(s, m, "Config file has invalid format");
01221       return 0;
01222    }
01223    astman_start_ack(s, m);
01224    while ((category = ast_category_browse(cfg, category))) {
01225       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
01226       catcount++;
01227    }
01228    if (catcount == 0) /* TODO: actually, a config with no categories doesn't even get loaded */
01229       astman_append(s, "Error: no categories found\r\n");
01230    ast_config_destroy(cfg);
01231    astman_append(s, "\r\n");
01232 
01233    return 0;
01234 }

static int action_listcommands ( struct mansession s,
const struct message m 
) [static]
Note:
The actionlock is read-locked by the caller of this function

Definition at line 1691 of file manager.c.

References manager_action::action, AST_RWLIST_TRAVERSE, ast_str_alloca, astman_append(), astman_start_ack(), manager_action::authority, authority_to_str(), mansession::session, manager_action::synopsis, and mansession_session::writeperm.

Referenced by __init_manager().

01692 {
01693    struct manager_action *cur;
01694    struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */
01695 
01696    astman_start_ack(s, m);
01697    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01698       if (s->session->writeperm & cur->authority || cur->authority == 0)
01699          astman_append(s, "%s: %s (Priv: %s)\r\n",
01700             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
01701    }
01702    astman_append(s, "\r\n");
01703 
01704    return 0;
01705 }

static int action_login ( struct mansession s,
const struct message m 
) [static]

Definition at line 1740 of file manager.c.

References ast_inet_ntoa(), ast_log(), ast_verb, astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, LOG_EVENT, manager_displayconnects(), mansession_session::managerid, mansession::session, mansession_session::sin, and mansession_session::username.

Referenced by __init_manager().

01741 {
01742    if (authenticate(s, m)) {
01743       sleep(1);
01744       astman_send_error(s, m, "Authentication failed");
01745       return -1;
01746    }
01747    s->session->authenticated = 1;
01748    if (manager_displayconnects(s->session))
01749       ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
01750    ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
01751    astman_send_ack(s, m, "Authentication accepted");
01752    return 0;
01753 }

static int action_logoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 1734 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

01735 {
01736    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
01737    return -1;
01738 }

static int action_mailboxcount ( struct mansession s,
const struct message m 
) [static]

Definition at line 2558 of file manager.c.

References ast_app_inboxcount2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.

Referenced by __init_manager().

02559 {
02560    const char *mailbox = astman_get_header(m, "Mailbox");
02561    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
02562 
02563    if (ast_strlen_zero(mailbox)) {
02564       astman_send_error(s, m, "Mailbox not specified");
02565       return 0;
02566    }
02567    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
02568    astman_start_ack(s, m);
02569    astman_append(s,   "Message: Mailbox Message Count\r\n"
02570             "Mailbox: %s\r\n"
02571             "UrgMessages: %d\r\n"
02572             "NewMessages: %d\r\n"
02573             "OldMessages: %d\r\n"
02574             "\r\n",
02575             mailbox, urgentmsgs, newmsgs, oldmsgs);
02576    return 0;
02577 }

static int action_mailboxstatus ( struct mansession s,
const struct message m 
) [static]

Definition at line 2529 of file manager.c.

References ast_app_has_voicemail(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.

Referenced by __init_manager().

02530 {
02531    const char *mailbox = astman_get_header(m, "Mailbox");
02532    int ret;
02533 
02534    if (ast_strlen_zero(mailbox)) {
02535       astman_send_error(s, m, "Mailbox not specified");
02536       return 0;
02537    }
02538    ret = ast_app_has_voicemail(mailbox, NULL);
02539    astman_start_ack(s, m);
02540    astman_append(s, "Message: Mailbox Status\r\n"
02541           "Mailbox: %s\r\n"
02542           "Waiting: %d\r\n\r\n", mailbox, ret);
02543    return 0;
02544 }

static int action_originate ( struct mansession s,
const struct message m 
) [static]

Definition at line 2392 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, app, fast_originate_helper::appdata, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, context, fast_originate_helper::data, ast_frame::data, EVENT_FLAG_SYSTEM, fast_originate_helper::exten, exten, fast_originate(), fast_originate_helper::format, format, fast_originate_helper::idtext, name, fast_originate_helper::priority, mansession::session, fast_originate_helper::tech, fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

02393 {
02394    const char *name = astman_get_header(m, "Channel");
02395    const char *exten = astman_get_header(m, "Exten");
02396    const char *context = astman_get_header(m, "Context");
02397    const char *priority = astman_get_header(m, "Priority");
02398    const char *timeout = astman_get_header(m, "Timeout");
02399    const char *callerid = astman_get_header(m, "CallerID");
02400    const char *account = astman_get_header(m, "Account");
02401    const char *app = astman_get_header(m, "Application");
02402    const char *appdata = astman_get_header(m, "Data");
02403    const char *async = astman_get_header(m, "Async");
02404    const char *id = astman_get_header(m, "ActionID");
02405    const char *codecs = astman_get_header(m, "Codecs");
02406    struct ast_variable *vars = astman_get_variables(m);
02407    char *tech, *data;
02408    char *l = NULL, *n = NULL;
02409    int pi = 0;
02410    int res;
02411    int to = 30000;
02412    int reason = 0;
02413    char tmp[256];
02414    char tmp2[256];
02415    int format = AST_FORMAT_SLINEAR;
02416 
02417    pthread_t th;
02418    if (ast_strlen_zero(name)) {
02419       astman_send_error(s, m, "Channel not specified");
02420       return 0;
02421    }
02422    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
02423       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
02424          astman_send_error(s, m, "Invalid priority");
02425          return 0;
02426       }
02427    }
02428    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
02429       astman_send_error(s, m, "Invalid timeout");
02430       return 0;
02431    }
02432    ast_copy_string(tmp, name, sizeof(tmp));
02433    tech = tmp;
02434    data = strchr(tmp, '/');
02435    if (!data) {
02436       astman_send_error(s, m, "Invalid channel");
02437       return 0;
02438    }
02439    *data++ = '\0';
02440    ast_copy_string(tmp2, callerid, sizeof(tmp2));
02441    ast_callerid_parse(tmp2, &n, &l);
02442    if (n) {
02443       if (ast_strlen_zero(n))
02444          n = NULL;
02445    }
02446    if (l) {
02447       ast_shrink_phone_number(l);
02448       if (ast_strlen_zero(l))
02449          l = NULL;
02450    }
02451    if (!ast_strlen_zero(codecs)) {
02452       format = 0;
02453       ast_parse_allow_disallow(NULL, &format, codecs, 1);
02454    }
02455    if (ast_true(async)) {
02456       struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
02457       if (!fast) {
02458          res = -1;
02459       } else {
02460          if (!ast_strlen_zero(id))
02461             snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id);
02462          ast_copy_string(fast->tech, tech, sizeof(fast->tech));
02463             ast_copy_string(fast->data, data, sizeof(fast->data));
02464          ast_copy_string(fast->app, app, sizeof(fast->app));
02465          ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
02466          if (l)
02467             ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
02468          if (n)
02469             ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
02470          fast->vars = vars;
02471          ast_copy_string(fast->context, context, sizeof(fast->context));
02472          ast_copy_string(fast->exten, exten, sizeof(fast->exten));
02473          ast_copy_string(fast->account, account, sizeof(fast->account));
02474          fast->format = format;
02475          fast->timeout = to;
02476          fast->priority = pi;
02477          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
02478             ast_free(fast);
02479             res = -1;
02480          } else {
02481             res = 0;
02482          }
02483       }
02484    } else if (!ast_strlen_zero(app)) {
02485       /* To run the System application (or anything else that goes to shell), you must have the additional System privilege */
02486       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
02487          && (
02488             strcasestr(app, "system") == 0 || /* System(rm -rf /)
02489                                                  TrySystem(rm -rf /)       */
02490             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
02491                                                  TryExec(System(rm -rf /)) */
02492             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
02493                                                  EAGI(/bin/rm,-rf /)       */
02494             strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
02495             strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
02496             )) {
02497          astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
02498          return 0;
02499       }
02500       res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
02501    } else {
02502       if (exten && context && pi)
02503          res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
02504       else {
02505          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
02506          return 0;
02507       }
02508    }
02509    if (!res)
02510       astman_send_ack(s, m, "Originate successfully queued");
02511    else
02512       astman_send_error(s, m, "Originate failed");
02513    return 0;
02514 }

static int action_ping ( struct mansession s,
const struct message m 
) [static]

Definition at line 1137 of file manager.c.

References ast_strlen_zero(), astman_append(), and astman_get_header().

Referenced by __init_manager().

01138 {
01139    const char *actionid = astman_get_header(m, "ActionID");
01140 
01141    astman_append(s, "Response: Success\r\n");
01142    if (!ast_strlen_zero(actionid)){
01143       astman_append(s, "ActionID: %s\r\n", actionid);
01144    }
01145    astman_append(s, "Ping: Pong\r\n\r\n");
01146    return 0;
01147 }

static int action_redirect ( struct mansession s,
const struct message m 
) [static]

action_redirect: The redirect manager command

Definition at line 2084 of file manager.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_findlabel_extension(), AST_FLAG_BRIDGE_HANGUP_DONT, ast_get_channel_by_name_locked(), ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), buf, chan, context, exten, name, ast_channel::pbx, and ast_channel::priority.

Referenced by __init_manager().

02085 {
02086    const char *name = astman_get_header(m, "Channel");
02087    const char *name2 = astman_get_header(m, "ExtraChannel");
02088    const char *exten = astman_get_header(m, "Exten");
02089    const char *context = astman_get_header(m, "Context");
02090    const char *priority = astman_get_header(m, "Priority");
02091    struct ast_channel *chan, *chan2 = NULL;
02092    int pi = 0;
02093    int res;
02094 
02095    if (ast_strlen_zero(name)) {
02096       astman_send_error(s, m, "Channel not specified");
02097       return 0;
02098    }
02099    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
02100       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
02101          astman_send_error(s, m, "Invalid priority");
02102          return 0;
02103       }
02104    }
02105    /* XXX watch out, possible deadlock - we are trying to get two channels!!! */
02106    chan = ast_get_channel_by_name_locked(name);
02107    if (!chan) {
02108       char buf[256];
02109       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
02110       astman_send_error(s, m, buf);
02111       return 0;
02112    }
02113    if (ast_check_hangup(chan)) {
02114       astman_send_error(s, m, "Redirect failed, channel not up.");
02115       ast_channel_unlock(chan);
02116       return 0;
02117    }
02118    if (!ast_strlen_zero(name2))
02119       chan2 = ast_get_channel_by_name_locked(name2);
02120    if (chan2 && ast_check_hangup(chan2)) {
02121       astman_send_error(s, m, "Redirect failed, extra channel not up.");
02122       ast_channel_unlock(chan);
02123       ast_channel_unlock(chan2);
02124       return 0;
02125    }
02126    if (chan->pbx) {
02127       ast_channel_lock(chan);
02128       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
02129       ast_channel_unlock(chan);
02130    }
02131    res = ast_async_goto(chan, context, exten, pi);
02132    if (!res) {
02133       if (!ast_strlen_zero(name2)) {
02134          if (chan2) {
02135             if (chan2->pbx) {
02136                ast_channel_lock(chan2);
02137                ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
02138                ast_channel_unlock(chan2);
02139             }
02140             res = ast_async_goto(chan2, context, exten, pi);
02141          } else {
02142             res = -1;
02143          }
02144          if (!res)
02145             astman_send_ack(s, m, "Dual Redirect successful");
02146          else
02147             astman_send_error(s, m, "Secondary redirect failed");
02148       } else
02149          astman_send_ack(s, m, "Redirect successful");
02150    } else
02151       astman_send_error(s, m, "Redirect failed");
02152    if (chan)
02153       ast_channel_unlock(chan);
02154    if (chan2)
02155       ast_channel_unlock(chan2);
02156    return 0;
02157 }

static int action_reload ( struct mansession s,
const struct message m 
) [static]

Send a reload event.

Definition at line 2794 of file manager.c.

References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.

Referenced by __init_manager().

02795 {
02796    const char *module = astman_get_header(m, "Module");
02797    int res = ast_module_reload(S_OR(module, NULL));
02798 
02799    if (res == 2)
02800       astman_send_ack(s, m, "Module Reloaded");
02801    else
02802       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
02803    return 0;
02804 }

static int action_sendtext ( struct mansession s,
const struct message m 
) [static]

Definition at line 2039 of file manager.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_sendtext(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.

Referenced by __init_manager().

02040 {
02041    struct ast_channel *c = NULL;
02042    const char *name = astman_get_header(m, "Channel");
02043    const char *textmsg = astman_get_header(m, "Message");
02044    int res = 0;
02045 
02046    if (ast_strlen_zero(name)) {
02047       astman_send_error(s, m, "No channel specified");
02048       return 0;
02049    }
02050 
02051    if (ast_strlen_zero(textmsg)) {
02052       astman_send_error(s, m, "No Message specified");
02053       return 0;
02054    }
02055 
02056    c = ast_get_channel_by_name_locked(name);
02057    if (!c) {
02058       astman_send_error(s, m, "No such channel");
02059       return 0;
02060    }
02061 
02062    res = ast_sendtext(c, textmsg);
02063    ast_channel_unlock(c);
02064    
02065    if (res > 0)
02066       astman_send_ack(s, m, "Success");
02067    else
02068       astman_send_error(s, m, "Failure");
02069    
02070    return res;
02071 }

static int action_setvar ( struct mansession s,
const struct message m 
) [static]

Definition at line 1803 of file manager.c.

References ast_channel_unlock, ast_func_write(), ast_get_channel_by_name_locked(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, pbx_builtin_setvar_helper(), and S_OR.

Referenced by __init_manager().

01804 {
01805    struct ast_channel *c = NULL;
01806    const char *name = astman_get_header(m, "Channel");
01807    const char *varname = astman_get_header(m, "Variable");
01808    const char *varval = astman_get_header(m, "Value");
01809    int res = 0;
01810    
01811    if (ast_strlen_zero(varname)) {
01812       astman_send_error(s, m, "No variable specified");
01813       return 0;
01814    }
01815 
01816    if (!ast_strlen_zero(name)) {
01817       c = ast_get_channel_by_name_locked(name);
01818       if (!c) {
01819          astman_send_error(s, m, "No such channel");
01820          return 0;
01821       }
01822    }
01823    if (varname[strlen(varname)-1] == ')') {
01824       char *function = ast_strdupa(varname);
01825       res = ast_func_write(c, function, varval);
01826    } else {
01827       pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
01828    }
01829 
01830    if (c)
01831       ast_channel_unlock(c);
01832    if (res == 0) {
01833       astman_send_ack(s, m, "Variable Set"); 
01834    } else {
01835       astman_send_error(s, m, "Variable not set");
01836    }
01837    return 0;
01838 }

static int action_status ( struct mansession s,
const struct message m 
) [static]

Manager "status" command to show channels.

Definition at line 1904 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, ast_channel::accountcode, AST_APP_ARG, ast_channel_unlock, ast_channel_walk_locked(), AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), ast_get_channel_by_name_locked(), AST_STANDARD_APP_ARGS, ast_state2str(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, ast_channel::name, name, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_OR, ast_cdr::start, str, and ast_channel::uniqueid.

Referenced by __init_manager().

01905 {
01906    const char *name = astman_get_header(m, "Channel");
01907    const char *cvariables = astman_get_header(m, "Variables");
01908    char *variables = ast_strdupa(S_OR(cvariables, ""));
01909    struct ast_channel *c;
01910    char bridge[256];
01911    struct timeval now = ast_tvnow();
01912    long elapsed_seconds = 0;
01913    int channels = 0;
01914    int all = ast_strlen_zero(name); /* set if we want all channels */
01915    const char *id = astman_get_header(m, "ActionID");
01916    char idText[256];
01917    AST_DECLARE_APP_ARGS(vars,
01918       AST_APP_ARG(name)[100];
01919    );
01920    struct ast_str *str = ast_str_create(1000);
01921 
01922    if (!ast_strlen_zero(id))
01923       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01924    else
01925       idText[0] = '\0';
01926 
01927    if (all)
01928       c = ast_channel_walk_locked(NULL);
01929    else {
01930       c = ast_get_channel_by_name_locked(name);
01931       if (!c) {
01932          astman_send_error(s, m, "No such channel");
01933          ast_free(str);
01934          return 0;
01935       }
01936    }
01937    astman_send_ack(s, m, "Channel status will follow");
01938 
01939    if (!ast_strlen_zero(cvariables)) {
01940       AST_STANDARD_APP_ARGS(vars, variables);
01941    }
01942 
01943    /* if we look by name, we break after the first iteration */
01944    while (c) {
01945       if (!ast_strlen_zero(cvariables)) {
01946          int i;
01947          ast_str_reset(str);
01948          for (i = 0; i < vars.argc; i++) {
01949             char valbuf[512], *ret = NULL;
01950 
01951             if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
01952                if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
01953                   valbuf[0] = '\0';
01954                }
01955                ret = valbuf;
01956             } else {
01957                pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
01958             }
01959 
01960             ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
01961          }
01962       }
01963 
01964       channels++;
01965       if (c->_bridge)
01966          snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
01967       else
01968          bridge[0] = '\0';
01969       if (c->pbx) {
01970          if (c->cdr) {
01971             elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01972          }
01973          astman_append(s,
01974          "Event: Status\r\n"
01975          "Privilege: Call\r\n"
01976          "Channel: %s\r\n"
01977          "CallerIDNum: %s\r\n"
01978          "CallerIDName: %s\r\n"
01979          "Accountcode: %s\r\n"
01980          "ChannelState: %d\r\n"
01981          "ChannelStateDesc: %s\r\n"
01982          "Context: %s\r\n"
01983          "Extension: %s\r\n"
01984          "Priority: %d\r\n"
01985          "Seconds: %ld\r\n"
01986          "%s"
01987          "Uniqueid: %s\r\n"
01988          "%s"
01989          "%s"
01990          "\r\n",
01991          c->name,
01992          S_OR(c->cid.cid_num, ""),
01993          S_OR(c->cid.cid_name, ""),
01994          c->accountcode,
01995          c->_state,
01996          ast_state2str(c->_state), c->context,
01997          c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
01998       } else {
01999          astman_append(s,
02000          "Event: Status\r\n"
02001          "Privilege: Call\r\n"
02002          "Channel: %s\r\n"
02003          "CallerIDNum: %s\r\n"
02004          "CallerIDName: %s\r\n"
02005          "Account: %s\r\n"
02006          "State: %s\r\n"
02007          "%s"
02008          "Uniqueid: %s\r\n"
02009          "%s"
02010          "%s"
02011          "\r\n",
02012          c->name,
02013          S_OR(c->cid.cid_num, "<unknown>"),
02014          S_OR(c->cid.cid_name, "<unknown>"),
02015          c->accountcode,
02016          ast_state2str(c->_state), bridge, c->uniqueid, ast_str_buffer(str), idText);
02017       }
02018       ast_channel_unlock(c);
02019       if (!all)
02020          break;
02021       c = ast_channel_walk_locked(c);
02022    }
02023    astman_append(s,
02024    "Event: StatusComplete\r\n"
02025    "%s"
02026    "Items: %d\r\n"
02027    "\r\n", idText, channels);
02028    ast_free(str);
02029    return 0;
02030 }

static int action_timeout ( struct mansession s,
const struct message m 
) [static]

Definition at line 2621 of file manager.c.

References ast_channel_setwhentohangup_tv(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.

Referenced by __init_manager().

02622 {
02623    struct ast_channel *c;
02624    const char *name = astman_get_header(m, "Channel");
02625    double timeout = atof(astman_get_header(m, "Timeout"));
02626    struct timeval when = { timeout, 0 };
02627 
02628    if (ast_strlen_zero(name)) {
02629       astman_send_error(s, m, "No channel specified");
02630       return 0;
02631    }
02632    if (!timeout || timeout < 0) {
02633       astman_send_error(s, m, "No timeout specified");
02634       return 0;
02635    }
02636    c = ast_get_channel_by_name_locked(name);
02637    if (!c) {
02638       astman_send_error(s, m, "No such channel");
02639       return 0;
02640    }
02641 
02642    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
02643    ast_channel_setwhentohangup_tv(c, when);
02644    ast_channel_unlock(c);
02645    astman_send_ack(s, m, "Timeout Set");
02646    return 0;
02647 }

static int action_updateconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 1481 of file manager.c.

References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save(), ast_include_rename(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_APPEND, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, handle_updates(), UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.

Referenced by __init_manager().

01482 {
01483    struct ast_config *cfg;
01484    const char *sfn = astman_get_header(m, "SrcFilename");
01485    const char *dfn = astman_get_header(m, "DstFilename");
01486    int res;
01487    const char *rld = astman_get_header(m, "Reload");
01488    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
01489    enum error_type result;
01490 
01491    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
01492       astman_send_error(s, m, "Filename not specified");
01493       return 0;
01494    }
01495    if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
01496       astman_send_error(s, m, "Config file not found");
01497       return 0;
01498    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01499       astman_send_error(s, m, "Config file has invalid format");
01500       return 0;
01501    }
01502    result = handle_updates(s, m, cfg, dfn);
01503    if (!result) {
01504       ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
01505       res = ast_config_text_file_save(dfn, cfg, "Manager");
01506       ast_config_destroy(cfg);
01507       if (res) {
01508          astman_send_error(s, m, "Save of config failed");
01509          return 0;
01510       }
01511       astman_send_ack(s, m, NULL);
01512       if (!ast_strlen_zero(rld)) {
01513          if (ast_true(rld))
01514             rld = NULL;
01515          ast_module_reload(rld);
01516       }
01517    } else {
01518       ast_config_destroy(cfg);
01519       switch(result) {
01520       case UNKNOWN_ACTION:
01521          astman_send_error(s, m, "Unknown action command");
01522          break;
01523       case UNKNOWN_CATEGORY:
01524          astman_send_error(s, m, "Given category does not exist");
01525          break;
01526       case UNSPECIFIED_CATEGORY:
01527          astman_send_error(s, m, "Category not specified");
01528          break;
01529       case UNSPECIFIED_ARGUMENT:
01530          astman_send_error(s, m, "Problem with category, value, or line (if required)");
01531          break;
01532       case FAILURE_ALLOCATION:
01533          astman_send_error(s, m, "Memory allocation failure, this should not happen");
01534          break;
01535       case FAILURE_NEWCAT:
01536          astman_send_error(s, m, "Create category did not complete successfully");
01537          break;
01538       case FAILURE_DELCAT:
01539          astman_send_error(s, m, "Delete category did not complete successfully");
01540          break;
01541       case FAILURE_EMPTYCAT:
01542          astman_send_error(s, m, "Empty category did not complete successfully");
01543          break;
01544       case FAILURE_UPDATE:
01545          astman_send_error(s, m, "Update did not complete successfully");
01546          break;
01547       case FAILURE_DELETE:
01548          astman_send_error(s, m, "Delete did not complete successfully");
01549          break;
01550       case FAILURE_APPEND:
01551          astman_send_error(s, m, "Append did not complete successfully");
01552          break;
01553       }
01554    }
01555    return 0;
01556 }

static int action_userevent ( struct mansession s,
const struct message m 
) [static]

Definition at line 2684 of file manager.c.

References ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_thread_get(), astman_get_header(), astman_send_ack(), EVENT_FLAG_USER, message::hdrcount, message::headers, manager_event, and userevent_buf.

Referenced by __init_manager().

02685 {
02686    const char *event = astman_get_header(m, "UserEvent");
02687    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
02688    int x;
02689 
02690    ast_str_reset(body);
02691 
02692    for (x = 0; x < m->hdrcount; x++) {
02693       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
02694          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
02695       }
02696    }
02697 
02698    astman_send_ack(s, m, "Event Sent");   
02699    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
02700    return 0;
02701 }

static int action_waitevent ( struct mansession s,
const struct message m 
) [static]

Definition at line 1591 of file manager.c.

References mansession_session::__lock, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_strlen_zero(), ast_wait_for_input(), astman_append(), astman_get_header(), astman_send_response(), eventqent::category, eventqent::eventdata, mansession_session::fd, mansession_session::last_ev, mansession_session::managerid, mansession_session::needdestroy, NEW_EVENT, mansession_session::readperm, ref_event(), mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, unref_event(), and mansession_session::waiting_thread.

Referenced by __init_manager().

01592 {
01593    const char *timeouts = astman_get_header(m, "Timeout");
01594    int timeout = -1;
01595    int x;
01596    int needexit = 0;
01597    const char *id = astman_get_header(m, "ActionID");
01598    char idText[256];
01599 
01600    if (!ast_strlen_zero(id))
01601       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01602    else
01603       idText[0] = '\0';
01604 
01605    if (!ast_strlen_zero(timeouts)) {
01606       sscanf(timeouts, "%30i", &timeout);
01607       if (timeout < -1)
01608          timeout = -1;
01609       /* XXX maybe put an upper bound, or prevent the use of 0 ? */
01610    }
01611 
01612    ast_mutex_lock(&s->session->__lock);
01613    if (s->session->waiting_thread != AST_PTHREADT_NULL)
01614       pthread_kill(s->session->waiting_thread, SIGURG);
01615 
01616    if (s->session->managerid) { /* AMI-over-HTTP session */
01617       /*
01618        * Make sure the timeout is within the expire time of the session,
01619        * as the client will likely abort the request if it does not see
01620        * data coming after some amount of time.
01621        */
01622       time_t now = time(NULL);
01623       int max = s->session->sessiontimeout - now - 10;
01624 
01625       if (max < 0)   /* We are already late. Strange but possible. */
01626          max = 0;
01627       if (timeout < 0 || timeout > max)
01628          timeout = max;
01629       if (!s->session->send_events) /* make sure we record events */
01630          s->session->send_events = -1;
01631    }
01632    ast_mutex_unlock(&s->session->__lock);
01633 
01634    /* XXX should this go inside the lock ? */
01635    s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
01636    ast_debug(1, "Starting waiting for an event!\n");
01637 
01638    for (x = 0; x < timeout || timeout < 0; x++) {
01639       ast_mutex_lock(&s->session->__lock);
01640       if (NEW_EVENT(s))
01641          needexit = 1;
01642       /* We can have multiple HTTP session point to the same mansession entry.
01643        * The way we deal with it is not very nice: newcomers kick out the previous
01644        * HTTP session. XXX this needs to be improved.
01645        */
01646       if (s->session->waiting_thread != pthread_self())
01647          needexit = 1;
01648       if (s->session->needdestroy)
01649          needexit = 1;
01650       ast_mutex_unlock(&s->session->__lock);
01651       if (needexit)
01652          break;
01653       if (s->session->managerid == 0) {   /* AMI session */
01654          if (ast_wait_for_input(s->session->fd, 1000))
01655             break;
01656       } else { /* HTTP session */
01657          sleep(1);
01658       }
01659    }
01660    ast_debug(1, "Finished waiting for an event!\n");
01661    ast_mutex_lock(&s->session->__lock);
01662    if (s->session->waiting_thread == pthread_self()) {
01663       struct eventqent *eqe;
01664       astman_send_response(s, m, "Success", "Waiting for Event completed.");
01665       while ( (eqe = NEW_EVENT(s)) ) {
01666          ref_event(eqe);
01667          if (((s->session->readperm & eqe->category) == eqe->category) &&
01668              ((s->session->send_events & eqe->category) == eqe->category)) {
01669             astman_append(s, "%s", eqe->eventdata);
01670          }
01671          s->session->last_ev = unref_event(s->session->last_ev);
01672       }
01673       astman_append(s,
01674          "Event: WaitEventComplete\r\n"
01675          "%s"
01676          "\r\n", idText);
01677       s->session->waiting_thread = AST_PTHREADT_NULL;
01678    } else {
01679       ast_debug(1, "Abandoning event request!\n");
01680    }
01681    ast_mutex_unlock(&s->session->__lock);
01682    return 0;
01683 }

static int append_event ( const char *  str,
int  category 
) [static]

Definition at line 3273 of file manager.c.

References ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, ast_malloc, eventqent::category, eventqent::eventdata, eventqent::seq, and eventqent::usecount.

Referenced by __init_manager(), and __manager_event().

03274 {
03275    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
03276    static int seq;   /* sequence number */
03277 
03278    if (!tmp)
03279       return -1;
03280 
03281    /* need to init all fields, because ast_malloc() does not */
03282    tmp->usecount = 0;
03283    tmp->category = category;
03284    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
03285    AST_LIST_NEXT(tmp, eq_next) = NULL;
03286    strcpy(tmp->eventdata, str);
03287 
03288    AST_LIST_LOCK(&all_events);
03289    AST_LIST_INSERT_TAIL(&all_events, tmp, eq_next);
03290    AST_LIST_UNLOCK(&all_events);
03291 
03292    return 0;
03293 }

static int ast_instring ( const char *  bigstr,
const char *  smallstr,
const char  delim 
) [static]

Tells you if smallstr exists inside bigstr which is delim by delim and uses no buf or stringsep ast_instring("this|that|more","this",'|') == 1;

feel free to move this to app.c -anthm

Definition at line 413 of file manager.c.

References eventqent::next.

Referenced by get_perm().

00414 {
00415    const char *val = bigstr, *next;
00416 
00417    do {
00418       if ((next = strchr(val, delim))) {
00419          if (!strncmp(val, smallstr, (next - val)))
00420             return 1;
00421          else
00422             continue;
00423       } else
00424          return !strcmp(smallstr, val);
00425    } while (*(val = (next + 1)));
00426 
00427    return 0;
00428 }

int ast_manager_register2 ( const char *  action,
int  auth,
int(*)(struct mansession *s, const struct message *m)  func,
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

Register a manager command with the manager interface.

Definition at line 3448 of file manager.c.

References manager_action::action, ast_calloc, ast_free, ast_manager_register_struct(), manager_action::authority, manager_action::description, manager_action::func, and manager_action::synopsis.

Referenced by __init_manager(), ast_features_init(), load_module(), and load_pbx().

03449 {
03450    struct manager_action *cur = NULL;
03451 
03452    if (!(cur = ast_calloc(1, sizeof(*cur))))
03453       return -1;
03454 
03455    cur->action = action;
03456    cur->authority = auth;
03457    cur->func = func;
03458    cur->synopsis = synopsis;
03459    cur->description = description;
03460 
03461    if (ast_manager_register_struct(cur)) {
03462       ast_free(cur);
03463       return -1;
03464    }
03465 
03466    return 0;
03467 }

void ast_manager_register_hook ( struct manager_custom_hook hook  ) 

Add a custom hook to be called when an event is fired.

Add a custom hook to be called when an event is fired

Parameters:
hook struct manager_custom_hook object to add

Definition at line 256 of file manager.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

00257 {
00258    AST_RWLIST_WRLOCK(&manager_hooks);
00259    AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list);
00260    AST_RWLIST_UNLOCK(&manager_hooks);
00261    return;
00262 }

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 3412 of file manager.c.

References manager_action::action, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_verb, LOG_ERROR, LOG_WARNING, and tv.

Referenced by ast_manager_register2().

03413 {
03414    struct manager_action *cur, *prev = NULL;
03415    struct timespec tv = { 5, };
03416 
03417    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03418       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03419       return -1;
03420    }
03421    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03422       int ret = strcasecmp(cur->action, act->action);
03423       if (ret == 0) {
03424          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
03425          AST_RWLIST_UNLOCK(&actions);
03426          return -1;
03427       }
03428       if (ret > 0) { /* Insert these alphabetically */
03429          prev = cur;
03430          break;
03431       }
03432    }
03433 
03434    if (prev)
03435       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
03436    else
03437       AST_RWLIST_INSERT_HEAD(&actions, act, list);
03438 
03439    ast_verb(2, "Manager registered action %s\n", act->action);
03440 
03441    AST_RWLIST_UNLOCK(&actions);
03442 
03443    return 0;
03444 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

Definition at line 3379 of file manager.c.

References manager_action::action, ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, ast_verb, LOG_ERROR, and tv.

Referenced by __unload_module(), and unload_module().

03380 {
03381    struct manager_action *cur;
03382    struct timespec tv = { 5, };
03383 
03384    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03385       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03386       return -1;
03387    }
03388    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
03389       if (!strcasecmp(action, cur->action)) {
03390          AST_RWLIST_REMOVE_CURRENT(list);
03391          ast_free(cur);
03392          ast_verb(2, "Manager unregistered action %s\n", action);
03393          break;
03394       }
03395    }
03396    AST_RWLIST_TRAVERSE_SAFE_END;
03397    AST_RWLIST_UNLOCK(&actions);
03398 
03399    return 0;
03400 }

void ast_manager_unregister_hook ( struct manager_custom_hook hook  ) 

Delete a custom hook to be called when an event is fired.

Delete a custom hook to be called when an event is fired

Parameters:
hook struct manager_custom_hook object to delete

Definition at line 265 of file manager.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

00266 {
00267    AST_RWLIST_WRLOCK(&manager_hooks);
00268    AST_RWLIST_REMOVE(&manager_hooks, hook, list);
00269    AST_RWLIST_UNLOCK(&manager_hooks);
00270    return;
00271 }

void astman_append ( struct mansession s,
const char *  fmt,
  ... 
)

utility functions for creating AMI replies

Definition at line 969 of file manager.c.

References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, buf, mansession_session::f, mansession::f, send_string(), and mansession::session.

Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), action_status(), action_waitevent(), ast_cli_netstats(), astman_send_response_full(), do_print(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_rpt_local_nodes(), manager_rpt_status(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), rpt_manager_do_stats(), rpt_manager_success(), and session_do().

00970 {
00971    va_list ap;
00972    struct ast_str *buf;
00973 
00974    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE)))
00975       return;
00976 
00977    va_start(ap, fmt);
00978    ast_str_set_va(&buf, 0, fmt, ap);
00979    va_end(ap);
00980 
00981    if (s->f != NULL || s->session->f != NULL) {
00982       send_string(s, ast_str_buffer(buf));
00983    } else {
00984       ast_verbose("fd == -1 in astman_append, should not happen\n");
00985    }
00986 }

const char* astman_get_header ( const struct message m,
char *  var 
)

Get header from mananger transaction.

Definition at line 897 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().

00898 {
00899    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
00900 }

struct ast_variable* astman_get_variables ( const struct message m  )  [read]

Get a linked list of the Variable: headers.

Definition at line 903 of file manager.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_variable_new(), message::hdrcount, message::headers, parse(), and var.

Referenced by action_originate(), and manager_sipnotify().

00904 {
00905    int varlen, x, y;
00906    struct ast_variable *head = NULL, *cur;
00907 
00908    AST_DECLARE_APP_ARGS(args,
00909       AST_APP_ARG(vars)[32];
00910    );
00911 
00912    varlen = strlen("Variable: ");
00913 
00914    for (x = 0; x < m->hdrcount; x++) {
00915       char *parse, *var, *val;
00916 
00917       if (strncasecmp("Variable: ", m->headers[x], varlen))
00918          continue;
00919       parse = ast_strdupa(m->headers[x] + varlen);
00920 
00921       AST_STANDARD_APP_ARGS(args, parse);
00922       if (!args.argc)
00923          continue;
00924       for (y = 0; y < args.argc; y++) {
00925          if (!args.vars[y])
00926             continue;
00927          var = val = ast_strdupa(args.vars[y]);
00928          strsep(&val, "=");
00929          if (!val || ast_strlen_zero(var))
00930             continue;
00931          cur = ast_variable_new(var, val, "");
00932          cur->next = head;
00933          head = cur;
00934       }
00935    }
00936 
00937    return head;
00938 }

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 
)

Send error in manager transaction.

Definition at line 1027 of file manager.c.

References astman_send_response_full().

Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_modulecheck(), manager_moduleload(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), meetmemute(), process_message(), rpt_manager_do_stats(), start_monitor_action(), and stop_monitor_action().

01028 {
01029    astman_send_response_full(s, m, "Error", error, NULL);
01030 }

void astman_send_listack ( struct mansession s,
const struct message m,
char *  msg,
char *  listflag 
)
void astman_send_response ( struct mansession s,
const struct message m,
char *  resp,
char *  msg 
)

Send response in manager transaction.

Definition at line 1022 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

01023 {
01024    astman_send_response_full(s, m, resp, msg, NULL);
01025 }

static void astman_send_response_full ( struct mansession s,
const struct message m,
char *  resp,
char *  msg,
char *  listflag 
) [static]

Definition at line 1005 of file manager.c.

References ast_strlen_zero(), astman_append(), astman_get_header(), and MSG_MOREDATA.

Referenced by astman_send_ack(), astman_send_error(), astman_send_listack(), astman_send_response(), and astman_start_ack().

01006 {
01007    const char *id = astman_get_header(m, "ActionID");
01008 
01009    astman_append(s, "Response: %s\r\n", resp);
01010    if (!ast_strlen_zero(id))
01011       astman_append(s, "ActionID: %s\r\n", id);
01012    if (listflag)
01013       astman_append(s, "Eventlist: %s\r\n", listflag);   /* Start, complete, cancelled */
01014    if (msg == MSG_MOREDATA)
01015       return;
01016    else if (msg)
01017       astman_append(s, "Message: %s\r\n\r\n", msg);
01018    else
01019       astman_append(s, "\r\n");
01020 }

static void astman_start_ack ( struct mansession s,
const struct message m 
) [static]
static int authenticate ( struct mansession s,
const struct message m 
) [static]

Definition at line 1071 of file manager.c.

References ast_apply_ha(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), astman_get_header(), mansession_session::challenge, get_manager_by_name_locked(), ast_manager_user::ha, len(), LOG_NOTICE, MD5Final(), MD5Init(), MD5Update(), ast_manager_user::readperm, mansession_session::readperm, S_OR, ast_manager_user::secret, mansession::session, mansession_session::sessionstart, set_eventmask(), mansession_session::sin, mansession_session::username, ast_manager_user::writeperm, mansession_session::writeperm, ast_manager_user::writetimeout, and mansession_session::writetimeout.

Referenced by action_login().

01072 {
01073    const char *username = astman_get_header(m, "Username");
01074    const char *password = astman_get_header(m, "Secret");
01075    int error = -1;
01076    struct ast_manager_user *user = NULL;
01077 
01078    if (ast_strlen_zero(username))   /* missing username */
01079       return -1;
01080 
01081    /* locate user in locked state */
01082    AST_RWLIST_WRLOCK(&users);
01083 
01084    if (!(user = get_manager_by_name_locked(username))) {
01085       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
01086    } else if (user->ha && !ast_apply_ha(user->ha, &(s->session->sin))) {
01087       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
01088    } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
01089       const char *key = astman_get_header(m, "Key");
01090       if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
01091          int x;
01092          int len = 0;
01093          char md5key[256] = "";
01094          struct MD5Context md5;
01095          unsigned char digest[16];
01096 
01097          MD5Init(&md5);
01098          MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
01099          MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
01100          MD5Final(digest, &md5);
01101          for (x = 0; x < 16; x++)
01102             len += sprintf(md5key + len, "%2.2x", digest[x]);
01103          if (!strcmp(md5key, key))
01104             error = 0;
01105       } else {
01106          ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n", 
01107             S_OR(s->session->challenge, ""));
01108       }
01109    } else if (password && user->secret && !strcmp(password, user->secret))
01110       error = 0;
01111 
01112    if (error) {
01113       ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
01114       AST_RWLIST_UNLOCK(&users);
01115       return -1;
01116    }
01117 
01118    /* auth complete */
01119    
01120    ast_copy_string(s->session->username, username, sizeof(s->session->username));
01121    s->session->readperm = user->readperm;
01122    s->session->writeperm = user->writeperm;
01123    s->session->writetimeout = user->writetimeout;
01124    s->session->sessionstart = time(NULL);
01125    set_eventmask(s, astman_get_header(m, "Events"));
01126    
01127    AST_RWLIST_UNLOCK(&users);
01128    return 0;
01129 }

static char* authority_to_str ( int  authority,
struct ast_str **  res 
) [static]

Convert authority code to a list of options.

Definition at line 389 of file manager.c.

References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), num, and perms.

Referenced by __manager_event(), action_listcommands(), handle_showmanager(), handle_showmancmd(), and handle_showmancmds().

00390 {
00391    int i;
00392    char *sep = "";
00393 
00394    ast_str_reset(*res);
00395    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
00396       if (authority & perms[i].num) {
00397          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
00398          sep = ",";
00399       }
00400    }
00401 
00402    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
00403       ast_str_append(res, 0, "<none>");
00404 
00405    return ast_str_buffer(*res);
00406 }

static int check_blacklist ( const char *  cmd  )  [static]

Definition at line 2216 of file manager.c.

References ARRAY_LEN, ast_strip(), ast_strlen_zero(), command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, and words.

Referenced by action_command().

02217 {
02218    char *cmd_copy, *cur_cmd;
02219    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
02220    int i;
02221 
02222    cmd_copy = ast_strdupa(cmd);
02223    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
02224       cur_cmd = ast_strip(cur_cmd);
02225       if (ast_strlen_zero(cur_cmd)) {
02226          i--;
02227          continue;
02228       }
02229 
02230       cmd_words[i] = cur_cmd;
02231    }
02232 
02233    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
02234       int j, match = 1;
02235 
02236       for (j = 0; command_blacklist[i].words[j]; j++) {
02237          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
02238             match = 0;
02239             break;
02240          }
02241       }
02242 
02243       if (match) {
02244          return 1;
02245       }
02246    }
02247 
02248    return 0;
02249 }

int check_manager_enabled ( void   ) 

Event list management functions. We assume that the event list always has at least one element, and the delete code will not remove the last entry even if the.

Check if AMI is enabled.

Definition at line 316 of file manager.c.

Referenced by handle_show_settings().

00317 {
00318    return manager_enabled;
00319 }

static int check_manager_session_inuse ( const char *  name  )  [static]

Definition at line 472 of file manager.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, mansession_session::list, and mansession_session::username.

Referenced by process_message().

00473 {
00474    struct mansession_session *session = NULL;
00475 
00476    AST_LIST_LOCK(&sessions);
00477    AST_LIST_TRAVERSE(&sessions, session, list) {
00478       if (!strcasecmp(session->username, name)) 
00479          break;
00480    }
00481    AST_LIST_UNLOCK(&sessions);
00482 
00483    return session ? 1 : 0;
00484 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 321 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

00322 {
00323    return (webmanager_enabled && manager_enabled);
00324 }

static void destroy_session ( struct mansession_session session  )  [static]

Definition at line 852 of file manager.c.

References ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free_session().

Referenced by generic_http_callback(), and session_do().

00853 {
00854    AST_LIST_LOCK(&sessions);
00855    AST_LIST_REMOVE(&sessions, session, list);
00856    ast_atomic_fetchadd_int(&num_sessions, -1);
00857    free_session(session);
00858    AST_LIST_UNLOCK(&sessions);
00859 }

static int do_message ( struct mansession s  )  [static]

Definition at line 3137 of file manager.c.

References AST_MAX_MANHEADERS, ast_strlen_zero(), get_input(), message::hdrcount, message::headers, mansession_session::inbuf, process_events(), process_message(), and mansession::session.

Referenced by session_do().

03138 {
03139    struct message m = { 0 };
03140    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
03141    int res;
03142 
03143    for (;;) {
03144       /* Check if any events are pending and do them if needed */
03145       if (process_events(s))
03146          return -1;
03147       res = get_input(s, header_buf);
03148       if (res == 0) {
03149          continue;
03150       } else if (res > 0) {
03151          if (ast_strlen_zero(header_buf))
03152             return process_message(s, &m) ? -1 : 0;
03153          else if (m.hdrcount < (AST_MAX_MANHEADERS - 1))
03154             m.headers[m.hdrcount++] = ast_strdupa(header_buf);
03155       } else {
03156          return res;
03157       }
03158    }
03159 }

static void* fast_originate ( void *  data  )  [static]

Definition at line 2329 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, ast_free, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), chan, fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, fast_originate_helper::data, EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, manager_event, ast_channel::name, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, ast_channel::uniqueid, and fast_originate_helper::vars.

Referenced by action_originate().

02330 {
02331    struct fast_originate_helper *in = data;
02332    int res;
02333    int reason = 0;
02334    struct ast_channel *chan = NULL;
02335    char requested_channel[AST_CHANNEL_NAME];
02336 
02337    if (!ast_strlen_zero(in->app)) {
02338       res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
02339          S_OR(in->cid_num, NULL),
02340          S_OR(in->cid_name, NULL),
02341          in->vars, in->account, &chan);
02342    } else {
02343       res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
02344          S_OR(in->cid_num, NULL),
02345          S_OR(in->cid_name, NULL),
02346          in->vars, in->account, &chan);
02347    }
02348 
02349    if (!chan)
02350       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);   
02351    /* Tell the manager what happened with the channel */
02352    manager_event(EVENT_FLAG_CALL, "OriginateResponse",
02353       "%s%s"
02354       "Response: %s\r\n"
02355       "Channel: %s\r\n"
02356       "Context: %s\r\n"
02357       "Exten: %s\r\n"
02358       "Reason: %d\r\n"
02359       "Uniqueid: %s\r\n"
02360       "CallerIDNum: %s\r\n"
02361       "CallerIDName: %s\r\n",
02362       in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success", 
02363       chan ? chan->name : requested_channel, in->context, in->exten, reason, 
02364       chan ? chan->uniqueid : "<null>",
02365       S_OR(in->cid_num, "<unknown>"),
02366       S_OR(in->cid_name, "<unknown>")
02367       );
02368 
02369    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
02370    if (chan)
02371       ast_channel_unlock(chan);
02372    ast_free(in);
02373    return NULL;
02374 }

static void free_session ( struct mansession_session session  )  [static]

Definition at line 834 of file manager.c.

References mansession_session::__lock, ast_datastore_free(), ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_destroy(), mansession_session::datastores, ast_datastore::entry, mansession_session::f, mansession_session::last_ev, and unref_event().

Referenced by destroy_session(), and purge_sessions().

00835 {
00836    struct eventqent *eqe = session->last_ev;
00837    struct ast_datastore *datastore;
00838 
00839    /* Get rid of each of the data stores on the session */
00840    while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
00841       /* Free the data store */
00842       ast_datastore_free(datastore);
00843    }
00844 
00845    if (session->f != NULL)
00846       fclose(session->f);
00847    ast_mutex_destroy(&session->__lock);
00848    ast_free(session);
00849    unref_event(eqe);
00850 }

static int get_input ( struct mansession s,
char *  output 
) [static]

Read one full line (including crlf) from the manager socket.

Note:
 * \r\n is the only valid terminator for the line.
 * (Note that, later, '\0' will be considered as the end-of-line marker,
 * so everything between the '\0' and the '\r\n' will not be used).
 * Also note that we assume output to have at least "maxlen" space.
 * 

Definition at line 3067 of file manager.c.

References mansession_session::__lock, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_wait_for_input(), errno, mansession_session::f, mansession_session::fd, mansession_session::inbuf, mansession_session::inlen, LOG_WARNING, mansession_session::pending_event, mansession::session, mansession_session::sin, ast_frame::src, and mansession_session::waiting_thread.

Referenced by do_message().

03068 {
03069    int res, x;
03070    int maxlen = sizeof(s->session->inbuf) - 1;
03071    char *src = s->session->inbuf;
03072 
03073    /*
03074     * Look for \r\n within the buffer. If found, copy to the output
03075     * buffer and return, trimming the \r\n (not used afterwards).
03076     */
03077    for (x = 0; x < s->session->inlen; x++) {
03078       int cr;  /* set if we have \r */
03079       if (src[x] == '\r' && x+1 < s->session->inlen && src[x+1] == '\n')
03080          cr = 2;  /* Found. Update length to include \r\n */
03081       else if (src[x] == '\n')
03082          cr = 1;  /* also accept \n only */
03083       else
03084          continue;
03085       memmove(output, src, x);   /*... but trim \r\n */
03086       output[x] = '\0';    /* terminate the string */
03087       x += cr;       /* number of bytes used */
03088       s->session->inlen -= x;       /* remaining size */
03089       memmove(src, src + x, s->session->inlen); /* remove used bytes */
03090       return 1;
03091    }
03092    if (s->session->inlen >= maxlen) {
03093       /* no crlf found, and buffer full - sorry, too long for us */
03094       ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
03095       s->session->inlen = 0;
03096    }
03097    res = 0;
03098    while (res == 0) {
03099       /* XXX do we really need this locking ? */
03100       ast_mutex_lock(&s->session->__lock);
03101       if (s->session->pending_event) {
03102          s->session->pending_event = 0;
03103          ast_mutex_unlock(&s->session->__lock);
03104          return 0;
03105       }
03106       s->session->waiting_thread = pthread_self();
03107       ast_mutex_unlock(&s->session->__lock);
03108 
03109       res = ast_wait_for_input(s->session->fd, -1);   /* return 0 on timeout ? */
03110 
03111       ast_mutex_lock(&s->session->__lock);
03112       s->session->waiting_thread = AST_PTHREADT_NULL;
03113       ast_mutex_unlock(&s->session->__lock);
03114    }
03115    if (res < 0) {
03116       /* If we get a signal from some other thread (typically because
03117        * there are new events queued), return 0 to notify the caller.
03118        */
03119       if (errno == EINTR || errno == EAGAIN)
03120          return 0;
03121       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
03122       return -1;
03123    }
03124    ast_mutex_lock(&s->session->__lock);
03125    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
03126    if (res < 1)
03127       res = -1;   /* error return */
03128    else {
03129       s->session->inlen += res;
03130       src[s->session->inlen] = '\0';
03131       res = 0;
03132    }
03133    ast_mutex_unlock(&s->session->__lock);
03134    return res;
03135 }

static struct ast_manager_user* get_manager_by_name_locked ( const char *  name  )  [static, read]

lookup an entry in the list of registered users. must be called with the list lock held.

Definition at line 491 of file manager.c.

References AST_RWLIST_TRAVERSE, ast_manager_user::list, and ast_manager_user::username.

Referenced by __init_manager(), authenticate(), handle_showmanager(), and manager_displayconnects().

00492 {
00493    struct ast_manager_user *user = NULL;
00494 
00495    AST_RWLIST_TRAVERSE(&users, user, list)
00496       if (!strcasecmp(user->username, name))
00497          break;
00498    return user;
00499 }

static int get_perm ( const char *  instr  )  [static]

Definition at line 430 of file manager.c.

References ARRAY_LEN, ast_instring(), num, and perms.

Referenced by __init_manager(), and strings_to_mask().

00431 {
00432    int x = 0, ret = 0;
00433 
00434    if (!instr)
00435       return 0;
00436 
00437    for (x = 0; x < ARRAY_LEN(perms); x++) {
00438       if (ast_instring(instr, perms[x].label, ','))
00439          ret |= perms[x].num;
00440    }
00441 
00442    return ret;
00443 }

static struct eventqent* grab_last ( void   )  [static, read]

Grab a reference to the last event, update usecount as needed. Can handle a NULL pointer.

Definition at line 330 of file manager.c.

References ast_atomic_fetchadd_int(), AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_UNLOCK, and eventqent::usecount.

Referenced by generic_http_callback(), and session_do().

00331 {
00332    struct eventqent *ret;
00333 
00334    AST_LIST_LOCK(&all_events);
00335    ret = AST_LIST_LAST(&all_events);
00336    /* the list is never empty now, but may become so when
00337     * we optimize it in the future, so be prepared.
00338     */
00339    if (ret)
00340       ast_atomic_fetchadd_int(&ret->usecount, 1);
00341    AST_LIST_UNLOCK(&all_events);
00342    return ret;
00343 }

static char* handle_manager_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command manager reload.

Definition at line 784 of file manager.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, reload_manager(), and ast_cli_entry::usage.

00785 {
00786    switch (cmd) {
00787    case CLI_INIT:
00788       e->command = "manager reload";
00789       e->usage =
00790          "Usage: manager reload\n"
00791          "       Reloads the manager configuration.\n";
00792       return NULL;
00793    case CLI_GENERATE:
00794       return NULL;
00795    }
00796    if (a->argc > 2)
00797       return CLI_SHOWUSAGE;
00798    reload_manager();
00799    return CLI_SUCCESS;
00800 }

static char* handle_mandebug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 565 of file manager.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

00566 {
00567    switch (cmd) {
00568    case CLI_INIT:
00569       e->command = "manager set debug [on|off]";
00570       e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
00571       return NULL;
00572    case CLI_GENERATE:
00573       return NULL;   
00574    }
00575    if (a->argc == 3)
00576       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
00577    else if (a->argc == 4) {
00578       if (!strcasecmp(a->argv[3], "on"))
00579          manager_debug = 1;
00580       else if (!strcasecmp(a->argv[3], "off"))
00581          manager_debug = 0;
00582       else
00583          return CLI_SHOWUSAGE;
00584    }
00585    return CLI_SUCCESS;
00586 }

static char* handle_showmanager ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 588 of file manager.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_manager_user::displayconnects, ast_cli_args::fd, get_manager_by_name_locked(), ast_manager_user::ha, ast_cli_args::n, ast_cli_args::pos, ast_manager_user::readperm, ast_manager_user::secret, ast_cli_entry::usage, ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.

00589 {
00590    struct ast_manager_user *user = NULL;
00591    int l, which;
00592    char *ret = NULL;
00593    struct ast_str *rauthority = ast_str_alloca(128);
00594    struct ast_str *wauthority = ast_str_alloca(128);
00595 
00596    switch (cmd) {
00597    case CLI_INIT:
00598       e->command = "manager show user";
00599       e->usage = 
00600          " Usage: manager show user <user>\n"
00601          "        Display all information related to the manager user specified.\n";
00602       return NULL;
00603    case CLI_GENERATE:
00604       l = strlen(a->word);
00605       which = 0;
00606       if (a->pos != 3)
00607          return NULL;
00608       AST_RWLIST_RDLOCK(&users);
00609       AST_RWLIST_TRAVERSE(&users, user, list) {
00610          if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
00611             ret = ast_strdup(user->username);
00612             break;
00613          }
00614       }
00615       AST_RWLIST_UNLOCK(&users);
00616       return ret;
00617    }
00618 
00619    if (a->argc != 4)
00620       return CLI_SHOWUSAGE;
00621 
00622    AST_RWLIST_RDLOCK(&users);
00623 
00624    if (!(user = get_manager_by_name_locked(a->argv[3]))) {
00625       ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
00626       AST_RWLIST_UNLOCK(&users);
00627       return CLI_SUCCESS;
00628    }
00629 
00630    ast_cli(a->fd, "\n");
00631    ast_cli(a->fd,
00632       "       username: %s\n"
00633       "         secret: %s\n"
00634       "            acl: %s\n"
00635       "      read perm: %s\n"
00636       "     write perm: %s\n"
00637       "displayconnects: %s\n",
00638       (user->username ? user->username : "(N/A)"),
00639       (user->secret ? "<Set>" : "(N/A)"),
00640       (user->ha ? "yes" : "no"),
00641       authority_to_str(user->readperm, &rauthority),
00642       authority_to_str(user->writeperm, &wauthority),
00643       (user->displayconnects ? "yes" : "no"));
00644 
00645    AST_RWLIST_UNLOCK(&users);
00646 
00647    return CLI_SUCCESS;
00648 }

static char* handle_showmanagers ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 651 of file manager.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_manager_user::list, ast_cli_entry::usage, and ast_manager_user::username.

00652 {
00653    struct ast_manager_user *user = NULL;
00654    int count_amu = 0;
00655    switch (cmd) {
00656    case CLI_INIT:
00657       e->command = "manager show users";
00658       e->usage = 
00659          "Usage: manager show users\n"
00660          "       Prints a listing of all managers that are currently configured on that\n"
00661          " system.\n";
00662       return NULL;
00663    case CLI_GENERATE:
00664       return NULL;
00665    }
00666    if (a->argc != 3)
00667       return CLI_SHOWUSAGE;
00668 
00669    AST_RWLIST_RDLOCK(&users);
00670 
00671    /* If there are no users, print out something along those lines */
00672    if (AST_RWLIST_EMPTY(&users)) {
00673       ast_cli(a->fd, "There are no manager users.\n");
00674       AST_RWLIST_UNLOCK(&users);
00675       return CLI_SUCCESS;
00676    }
00677 
00678    ast_cli(a->fd, "\nusername\n--------\n");
00679 
00680    AST_RWLIST_TRAVERSE(&users, user, list) {
00681       ast_cli(a->fd, "%s\n", user->username);
00682       count_amu++;
00683    }
00684 
00685    AST_RWLIST_UNLOCK(&users);
00686 
00687    ast_cli(a->fd, "-------------------\n");
00688    ast_cli(a->fd, "%d manager users configured.\n", count_amu);
00689 
00690    return CLI_SUCCESS;
00691 }

static char* handle_showmancmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 518 of file manager.c.

References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, manager_action::description, ast_cli_args::fd, ast_cli_args::n, num, S_OR, manager_action::synopsis, ast_cli_entry::usage, and ast_cli_args::word.

00519 {
00520    struct manager_action *cur;
00521    struct ast_str *authority;
00522    int num, l, which;
00523    char *ret = NULL;
00524    switch (cmd) {
00525    case CLI_INIT:
00526       e->command = "manager show command";
00527       e->usage = 
00528          "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
00529          "  Shows the detailed description for a specific Asterisk manager interface command.\n";
00530       return NULL;
00531    case CLI_GENERATE:
00532       l = strlen(a->word);
00533       which = 0;
00534       AST_RWLIST_RDLOCK(&actions);
00535       AST_RWLIST_TRAVERSE(&actions, cur, list) {
00536          if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
00537             ret = ast_strdup(cur->action);
00538             break;   /* make sure we exit even if ast_strdup() returns NULL */
00539          }
00540       }
00541       AST_RWLIST_UNLOCK(&actions);
00542       return ret;
00543    }
00544    authority = ast_str_alloca(80);
00545    if (a->argc < 4) {
00546       return CLI_SHOWUSAGE;
00547    }
00548 
00549    AST_RWLIST_RDLOCK(&actions);
00550    AST_RWLIST_TRAVERSE(&actions, cur, list) {
00551       for (num = 3; num < a->argc; num++) {
00552          if (!strcasecmp(cur->action, a->argv[num])) {
00553             ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
00554                cur->action, cur->synopsis,
00555                authority_to_str(cur->authority, &authority),
00556                S_OR(cur->description, ""));
00557          }
00558       }
00559    }
00560    AST_RWLIST_UNLOCK(&actions);
00561 
00562    return CLI_SUCCESS;
00563 }

static char* handle_showmancmds ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command manager list commands.

Definition at line 695 of file manager.c.

References manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMC_FORMAT, manager_action::synopsis, and ast_cli_entry::usage.

00696 {
00697    struct manager_action *cur;
00698    struct ast_str *authority;
00699 #define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
00700    switch (cmd) {
00701    case CLI_INIT:
00702       e->command = "manager show commands";
00703       e->usage = 
00704          "Usage: manager show commands\n"
00705          "  Prints a listing of all the available Asterisk manager interface commands.\n";
00706       return NULL;
00707    case CLI_GENERATE:
00708       return NULL;   
00709    }  
00710    authority = ast_str_alloca(80);
00711    ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
00712    ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
00713 
00714    AST_RWLIST_RDLOCK(&actions);
00715    AST_RWLIST_TRAVERSE(&actions, cur, list)
00716       ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
00717    AST_RWLIST_UNLOCK(&actions);
00718 
00719    return CLI_SUCCESS;
00720 }

static char* handle_showmanconn ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command manager list connected.

Definition at line 723 of file manager.c.

References ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, mansession_session::fd, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, mansession_session::inuse, mansession_session::list, mansession_session::readperm, mansession_session::sessionstart, mansession_session::sin, ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.

00724 {
00725    struct mansession_session *session;
00726    time_t now = time(NULL);
00727 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
00728 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
00729    int count = 0;
00730    switch (cmd) {
00731    case CLI_INIT:
00732       e->command = "manager show connected";
00733       e->usage = 
00734          "Usage: manager show connected\n"
00735          "  Prints a listing of the users that are currently connected to the\n"
00736          "Asterisk manager interface.\n";
00737       return NULL;
00738    case CLI_GENERATE:
00739       return NULL;   
00740    }
00741 
00742    ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
00743 
00744    AST_LIST_LOCK(&sessions);
00745    AST_LIST_TRAVERSE(&sessions, session, list) {
00746       ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
00747       count++;
00748    }
00749    AST_LIST_UNLOCK(&sessions);
00750 
00751    ast_cli(a->fd, "%d users connected.\n", count);
00752 
00753    return CLI_SUCCESS;
00754 }

static char* handle_showmaneventq ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command manager list eventq.

Definition at line 758 of file manager.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, eventqent::category, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, eventqent::eventdata, ast_cli_args::fd, s, ast_cli_entry::usage, and eventqent::usecount.

00759 {
00760    struct eventqent *s;
00761    switch (cmd) {
00762    case CLI_INIT:
00763       e->command = "manager show eventq";
00764       e->usage = 
00765          "Usage: manager show eventq\n"
00766          "  Prints a listing of all events pending in the Asterisk manger\n"
00767          "event queue.\n";
00768       return NULL;
00769    case CLI_GENERATE:
00770       return NULL;
00771    }
00772    AST_LIST_LOCK(&all_events);
00773    AST_LIST_TRAVERSE(&all_events, s, eq_next) {
00774       ast_cli(a->fd, "Usecount: %d\n", s->usecount);
00775       ast_cli(a->fd, "Category: %d\n", s->category);
00776       ast_cli(a->fd, "Event:\n%s", s->eventdata);
00777    }
00778    AST_LIST_UNLOCK(&all_events);
00779 
00780    return CLI_SUCCESS;
00781 }

static enum error_type handle_updates ( struct mansession s,
const struct message m,
struct ast_config cfg,
const char *  dfn 
) [static]

Definition at line 1324 of file manager.c.

References ast_category_append(), ast_category_delete(), ast_category_empty(), ast_category_get(), ast_category_insert(), ast_category_new(), ast_category_rename(), ast_free, ast_log(), ast_str_create(), ast_strlen_zero(), ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new(), ast_variable_update(), astman_get_header(), eventqent::category, FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, LOG_WARNING, match(), ast_variable::object, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, and var.

Referenced by action_updateconfig().

01325 {
01326    int x;
01327    char hdr[40];
01328    const char *action, *cat, *var, *value, *match, *line;
01329    struct ast_category *category;
01330    struct ast_variable *v;
01331    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
01332    enum error_type result = 0;
01333 
01334    for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
01335       unsigned int object = 0;
01336 
01337       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
01338       action = astman_get_header(m, hdr);
01339       if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
01340          break;                        /* this could cause problems if actions come in misnumbered */
01341 
01342       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
01343       cat = astman_get_header(m, hdr);
01344       if (ast_strlen_zero(cat)) {      /* every action needs a category */
01345          result =  UNSPECIFIED_CATEGORY;
01346          break;
01347       }
01348 
01349       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
01350       var = astman_get_header(m, hdr);
01351 
01352       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
01353       value = astman_get_header(m, hdr);
01354 
01355       if (!ast_strlen_zero(value) && *value == '>') {
01356          object = 1;
01357          value++;
01358       }
01359    
01360       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
01361       match = astman_get_header(m, hdr);
01362 
01363       snprintf(hdr, sizeof(hdr), "Line-%06d", x);
01364       line = astman_get_header(m, hdr);
01365 
01366       if (!strcasecmp(action, "newcat")) {
01367          if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */
01368             result = FAILURE_NEWCAT;   /* already exist */
01369             break;
01370          }
01371          if (!(category = ast_category_new(cat, dfn, -1))) {
01372             result = FAILURE_ALLOCATION;
01373             break;
01374          }
01375          if (ast_strlen_zero(match)) {
01376             ast_category_append(cfg, category);
01377          } else
01378             ast_category_insert(cfg, category, match);
01379       } else if (!strcasecmp(action, "renamecat")) {
01380          if (ast_strlen_zero(value)) {
01381             result = UNSPECIFIED_ARGUMENT;
01382             break;
01383          }
01384          if (!(category = ast_category_get(cfg, cat))) {
01385             result = UNKNOWN_CATEGORY;
01386             break;
01387          }
01388          ast_category_rename(category, value);
01389       } else if (!strcasecmp(action, "delcat")) {
01390          if (ast_category_delete(cfg, cat)) {
01391             result = FAILURE_DELCAT;
01392             break;
01393          }
01394       } else if (!strcasecmp(action, "emptycat")) {
01395          if (ast_category_empty(cfg, cat)) {
01396             result = FAILURE_EMPTYCAT;
01397             break;
01398          }
01399       } else if (!strcasecmp(action, "update")) {
01400          if (ast_strlen_zero(var)) {
01401             result = UNSPECIFIED_ARGUMENT;
01402             break;
01403          }
01404          if (!(category = ast_category_get(cfg,cat))) {
01405             result = UNKNOWN_CATEGORY;
01406             break;
01407          }
01408          if (ast_variable_update(category, var, value, match, object)) {
01409             result = FAILURE_UPDATE;
01410             break;
01411          }
01412       } else if (!strcasecmp(action, "delete")) {
01413          if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
01414             result = UNSPECIFIED_ARGUMENT;
01415             break;
01416          }
01417          if (!(category = ast_category_get(cfg, cat))) {
01418             result = UNKNOWN_CATEGORY;
01419             break;
01420          }
01421          if (ast_variable_delete(category, var, match, line)) {
01422             result = FAILURE_DELETE;
01423             break;
01424          }
01425       } else if (!strcasecmp(action, "append")) {
01426          if (ast_strlen_zero(var)) {
01427             result = UNSPECIFIED_ARGUMENT;
01428             break;
01429          }
01430          if (!(category = ast_category_get(cfg, cat))) {
01431             result = UNKNOWN_CATEGORY; 
01432             break;
01433          }
01434          if (!(v = ast_variable_new(var, value, dfn))) {
01435             result = FAILURE_ALLOCATION;
01436             break;
01437          }
01438          if (object || (match && !strcasecmp(match, "object")))
01439             v->object = 1;
01440          ast_variable_append(category, v);
01441       } else if (!strcasecmp(action, "insert")) {
01442          if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
01443             result = UNSPECIFIED_ARGUMENT;
01444             break;
01445          }
01446          if (!(category = ast_category_get(cfg, cat))) {
01447             result = UNKNOWN_CATEGORY;
01448             break;
01449          }
01450          if (!(v = ast_variable_new(var, value, dfn))) {
01451             result = FAILURE_ALLOCATION;
01452             break;
01453          }
01454          ast_variable_insert(category, v, line);
01455       }
01456       else {
01457          ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
01458          result = UNKNOWN_ACTION;
01459          break;
01460       }
01461    }
01462    ast_free(str1);
01463    ast_free(str2);
01464    return result;
01465 }

static void json_escape ( char *  out,
const char *  in 
) [static]

The amount of space in out must be at least ( 2 * strlen(in) + 1 )

Definition at line 1240 of file manager.c.

Referenced by action_getconfigjson().

01241 {
01242    for (; *in; in++) {
01243       if (*in == '\\' || *in == '\"')
01244          *out++ = '\\';
01245       *out++ = *in;
01246    }
01247    *out = '\0';
01248 }

static int manager_displayconnects ( struct mansession_session session  )  [static]

Get displayconnects config option.

Parameters:
session manager session to get parameter from.
Returns:
displayconnects config option value.

Definition at line 505 of file manager.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_manager_user::displayconnects, get_manager_by_name_locked(), and mansession_session::username.

Referenced by action_login(), generic_http_callback(), purge_sessions(), and session_do().

00506 {
00507    struct ast_manager_user *user = NULL;
00508    int ret = 0;
00509 
00510    AST_RWLIST_RDLOCK(&users);
00511    if ((user = get_manager_by_name_locked (session->username)))
00512       ret = user->displayconnects;
00513    AST_RWLIST_UNLOCK(&users);
00514    
00515    return ret;
00516 }

static int manager_modulecheck ( struct mansession s,
const struct message m 
) [static]

Definition at line 2885 of file manager.c.

References ast_copy_string(), ast_file_version_find(), ast_log(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), LOG_DEBUG, and version.

Referenced by __init_manager().

02886 {
02887    int res;
02888    const char *module = astman_get_header(m, "Module");
02889    const char *id = astman_get_header(m, "ActionID");
02890    char idText[256];
02891 #if !defined(LOW_MEMORY)
02892    const char *version;
02893 #endif
02894    char filename[PATH_MAX];
02895    char *cut;
02896 
02897    ast_copy_string(filename, module, sizeof(filename));
02898    if ((cut = strchr(filename, '.'))) {
02899       *cut = '\0';
02900    } else {
02901       cut = filename + strlen(filename);
02902    }
02903    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
02904    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
02905    res = ast_module_check(filename);
02906    if (!res) {
02907       astman_send_error(s, m, "Module not loaded");
02908       return 0;
02909    }
02910    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
02911    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
02912 #if !defined(LOW_MEMORY)
02913    version = ast_file_version_find(filename);
02914 #endif
02915 
02916    if (!ast_strlen_zero(id))
02917       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02918    else
02919       idText[0] = '\0';
02920    astman_append(s, "Response: Success\r\n%s", idText);
02921 #if !defined(LOW_MEMORY)
02922    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
02923 #endif
02924    return 0;
02925 }

static int manager_moduleload ( struct mansession s,
const struct message m 
) [static]

Definition at line 2938 of file manager.c.

References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), ast_unload_resource(), astman_get_header(), astman_send_ack(), and astman_send_error().

Referenced by __init_manager().

02939 {
02940    int res;
02941    const char *module = astman_get_header(m, "Module");
02942    const char *loadtype = astman_get_header(m, "LoadType");
02943 
02944    if (!loadtype || strlen(loadtype) == 0)
02945       astman_send_error(s, m, "Incomplete ModuleLoad action.");
02946    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0)
02947       astman_send_error(s, m, "Need module name");
02948 
02949    if (!strcasecmp(loadtype, "load")) {
02950       res = ast_load_resource(module);
02951       if (res)
02952          astman_send_error(s, m, "Could not load module.");
02953       else
02954          astman_send_ack(s, m, "Module loaded.");
02955    } else if (!strcasecmp(loadtype, "unload")) {
02956       res = ast_unload_resource(module, AST_FORCE_SOFT);
02957       if (res)
02958          astman_send_error(s, m, "Could not unload module.");
02959       else
02960          astman_send_ack(s, m, "Module unloaded.");
02961    } else if (!strcasecmp(loadtype, "reload")) {
02962       if (module != NULL) {
02963          res = ast_module_reload(module);
02964          if (res == 0)
02965             astman_send_error(s, m, "No such module.");
02966          else if (res == 1)
02967             astman_send_error(s, m, "Module does not support reload action.");
02968          else
02969             astman_send_ack(s, m, "Module reloaded.");
02970       } else {
02971          ast_module_reload(NULL);   /* Reload all modules */
02972          astman_send_ack(s, m, "All modules reloaded");
02973       }
02974    } else 
02975       astman_send_error(s, m, "Incomplete ModuleLoad action.");
02976    return 0;
02977 }

static int manager_state_cb ( char *  context,
char *  exten,
int  state,
void *  data 
) [static]

Definition at line 3402 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

03403 {
03404    /* Notify managers of change */
03405    char hint[512];
03406    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
03407 
03408    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
03409    return 0;
03410 }

static int process_events ( struct mansession s  )  [static]

Send any applicable events to the client listening on this socket. Wait only for a finite time on each event, and drop all events whether they are successfully sent or not.

Definition at line 2654 of file manager.c.

References mansession_session::__lock, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::authenticated, eventqent::category, eventqent::eventdata, mansession_session::f, mansession_session::last_ev, NEW_EVENT, mansession_session::readperm, ref_event(), mansession_session::send_events, send_string(), mansession::session, and unref_event().

Referenced by do_message(), and process_message().

02655 {
02656    int ret = 0;
02657 
02658    ast_mutex_lock(&s->session->__lock);
02659    if (s->session->f != NULL) {
02660       struct eventqent *eqe;
02661 
02662       while ( (eqe = NEW_EVENT(s)) ) {
02663          ref_event(eqe);
02664          if (!ret && s->session->authenticated &&
02665              (s->session->readperm & eqe->category) == eqe->category &&
02666              (s->session->send_events & eqe->category) == eqe->category) {
02667             if (send_string(s, eqe->eventdata) < 0)
02668                ret = -1;   /* don't send more */
02669          }
02670          s->session->last_ev = unref_event(s->session->last_ev);
02671       }
02672    }
02673    ast_mutex_unlock(&s->session->__lock);
02674    return ret;
02675 }

static int process_message ( struct mansession s,
const struct message m 
) [static]

Definition at line 2992 of file manager.c.

References __astman_get_header(), mansession_session::__lock, manager_action::action, ast_copy_string(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), astman_get_header(), astman_send_error(), mansession_session::authenticated, manager_action::authority, buf, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, process_events(), mansession::session, and mansession_session::writeperm.

Referenced by do_message(), and generic_http_callback().

02993 {
02994    char action[80] = "";
02995    int ret = 0;
02996    struct manager_action *tmp;
02997    const char *user = astman_get_header(m, "Username");
02998 
02999    ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));
03000    ast_debug(1, "Manager received command '%s'\n", action);
03001 
03002    if (ast_strlen_zero(action)) {
03003       ast_mutex_lock(&s->session->__lock);
03004       astman_send_error(s, m, "Missing action in request");
03005       ast_mutex_unlock(&s->session->__lock);
03006       return 0;
03007    }
03008 
03009    if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
03010       ast_mutex_lock(&s->session->__lock);
03011       astman_send_error(s, m, "Permission denied");
03012       ast_mutex_unlock(&s->session->__lock);
03013       return 0;
03014    }
03015 
03016    if (!allowmultiplelogin && !s->session->authenticated && user &&
03017       (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
03018       if (check_manager_session_inuse(user)) {
03019          sleep(1);
03020          ast_mutex_lock(&s->session->__lock);
03021          astman_send_error(s, m, "Login Already In Use");
03022          ast_mutex_unlock(&s->session->__lock);
03023          return -1;
03024       }
03025    }
03026 
03027    AST_RWLIST_RDLOCK(&actions);
03028    AST_RWLIST_TRAVERSE(&actions, tmp, list) {
03029       if (strcasecmp(action, tmp->action))
03030          continue;
03031       if (s->session->writeperm & tmp->authority || tmp->authority == 0)
03032          ret = tmp->func(s, m);
03033       else
03034          astman_send_error(s, m, "Permission denied");
03035       break;
03036    }
03037    AST_RWLIST_UNLOCK(&actions);
03038 
03039    if (!tmp) {
03040       char buf[512];
03041       snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
03042       ast_mutex_lock(&s->session->__lock);
03043       astman_send_error(s, m, buf);
03044       ast_mutex_unlock(&s->session->__lock);
03045    }
03046    if (ret)
03047       return ret;
03048    /* Once done with our message, deliver any pending events unless the
03049       requester doesn't want them as part of this response.
03050    */
03051    if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
03052       return process_events(s);
03053    } else {
03054       return ret;
03055    }
03056 }

static void purge_events ( void   )  [static]

Purge unused events. Remove elements from the head as long as their usecount is 0 and there is a next element.

Definition at line 349 of file manager.c.

References ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and eventqent::usecount.

Referenced by purge_old_stuff().

00350 {
00351    struct eventqent *ev;
00352 
00353    AST_LIST_LOCK(&all_events);
00354    while ( (ev = AST_LIST_FIRST(&all_events)) &&
00355        ev->usecount == 0 && AST_LIST_NEXT(ev, eq_next)) {
00356       AST_LIST_REMOVE_HEAD(&all_events, eq_next);
00357       ast_free(ev);
00358    }
00359    AST_LIST_UNLOCK(&all_events);
00360 }

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

Definition at line 3246 of file manager.c.

References ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verb, mansession_session::authenticated, free_session(), mansession_session::inuse, manager_displayconnects(), mansession_session::sessiontimeout, mansession_session::sin, mansession_session::username, and VERBOSITY_ATLEAST.

Referenced by purge_old_stuff().

03247 {
03248    struct mansession_session *session;
03249    time_t now = time(NULL);
03250 
03251    AST_LIST_LOCK(&sessions);
03252    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, session, list) {
03253       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
03254          AST_LIST_REMOVE_CURRENT(list);
03255          ast_atomic_fetchadd_int(&num_sessions, -1);
03256          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
03257             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
03258                session->username, ast_inet_ntoa(session->sin.sin_addr));
03259          }
03260          free_session(session);  /* XXX outside ? */
03261          if (--n_max <= 0)
03262             break;
03263       }
03264    }
03265    AST_LIST_TRAVERSE_SAFE_END;
03266    AST_LIST_UNLOCK(&sessions);
03267 }

static void ref_event ( struct eventqent e  )  [static]

Definition at line 826 of file manager.c.

References ast_atomic_fetchadd_int(), and eventqent::usecount.

Referenced by action_waitevent(), and process_events().

00827 {
00828    ast_atomic_fetchadd_int(&e->usecount, 1);
00829 }

static int send_string ( struct mansession s,
char *  string 
) [static]

helper function to send a string to the socket. Return -1 on error (e.g. buffer full).

Definition at line 944 of file manager.c.

References ast_careful_fwrite(), mansession_session::f, mansession::f, mansession_session::fd, mansession::fd, mansession::session, and mansession_session::writetimeout.

Referenced by astman_append(), and process_events().

00945 {
00946    if (s->f) {
00947       return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout);
00948    } else {
00949       return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout);
00950    }
00951 }

static void* session_do ( void *  data  )  [static]

The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).

Definition at line 3169 of file manager.c.

References mansession_session::__lock, AMI_VERSION, ao2_ref, ast_atomic_fetchadd_int(), ast_calloc, ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), AST_PTHREADT_NULL, ast_verb, astman_append(), mansession_session::authenticated, mansession_session::datastores, destroy_session(), do_message(), ast_tcptls_session_instance::f, mansession_session::f, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, LOG_EVENT, manager_displayconnects(), ast_tcptls_session_instance::remote_address, s, mansession_session::send_events, mansession::session, mansession_session::sin, mansession_session::username, mansession_session::waiting_thread, and mansession_session::writetimeout.

03170 {
03171    struct ast_tcptls_session_instance *ser = data;
03172    struct mansession_session *session = ast_calloc(1, sizeof(*session));
03173    struct mansession s = {.session = NULL, };
03174    int flags;
03175    int res;
03176 
03177    if (session == NULL)
03178       goto done;
03179 
03180    session->writetimeout = 100;
03181    session->waiting_thread = AST_PTHREADT_NULL;
03182 
03183    flags = fcntl(ser->fd, F_GETFL);
03184    if (!block_sockets) /* make sure socket is non-blocking */
03185       flags |= O_NONBLOCK;
03186    else
03187       flags &= ~O_NONBLOCK;
03188    fcntl(ser->fd, F_SETFL, flags);
03189 
03190    ast_mutex_init(&session->__lock);
03191    session->send_events = -1;
03192    /* Hook to the tail of the event queue */
03193    session->last_ev = grab_last();
03194 
03195    /* these fields duplicate those in the 'ser' structure */
03196    session->fd = ser->fd;
03197    session->f = ser->f;
03198    session->sin = ser->remote_address;
03199    s.session = session;
03200 
03201    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
03202 
03203    AST_LIST_LOCK(&sessions);
03204    AST_LIST_INSERT_HEAD(&sessions, session, list);
03205    ast_atomic_fetchadd_int(&num_sessions, 1);
03206    AST_LIST_UNLOCK(&sessions);
03207 
03208    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
03209    for (;;) {
03210       if ((res = do_message(&s)) < 0)
03211          break;
03212    }
03213    /* session is over, explain why and terminate */
03214    if (session->authenticated) {
03215          if (manager_displayconnects(session))
03216          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03217       ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
03218    } else {
03219          if (displayconnects)
03220          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
03221       ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
03222    }
03223 
03224    /* It is possible under certain circumstances for this session thread
03225       to complete its work and exit *before* the thread that created it
03226       has finished executing the ast_pthread_create_background() function.
03227       If this occurs, some versions of glibc appear to act in a buggy
03228       fashion and attempt to write data into memory that it thinks belongs
03229       to the thread but is in fact not owned by the thread (or may have
03230       been freed completely).
03231 
03232       Causing this thread to yield to other threads at least one time
03233       appears to work around this bug.
03234    */
03235    usleep(1);
03236 
03237    destroy_session(session);
03238 
03239 done:
03240    ao2_ref(ser, -1);
03241    ser = NULL;
03242    return NULL;
03243 }

static int set_eventmask ( struct mansession s,
const char *  eventmask 
) [static]

Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.

Definition at line 1052 of file manager.c.

References mansession_session::__lock, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::send_events, mansession::session, and strings_to_mask().

Referenced by action_events(), and authenticate().

01053 {
01054    int maskint = strings_to_mask(eventmask);
01055 
01056    ast_mutex_lock(&s->session->__lock);
01057    if (maskint >= 0)
01058       s->session->send_events = maskint;
01059    ast_mutex_unlock(&s->session->__lock);
01060 
01061    return maskint;
01062 }

static int strings_to_mask ( const char *  string  )  [static]

A number returns itself, false returns 0, true returns all flags, other strings return the flags that are set.

Definition at line 449 of file manager.c.

References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), num, and perms.

Referenced by set_eventmask().

00450 {
00451    const char *p;
00452 
00453    if (ast_strlen_zero(string))
00454       return -1;
00455 
00456    for (p = string; *p; p++)
00457       if (*p < '0' || *p > '9')
00458          break;
00459    if (!*p) /* all digits */
00460       return atoi(string);
00461    if (ast_false(string))
00462       return 0;
00463    if (ast_true(string)) { /* all permissions */
00464       int x, ret = 0;
00465       for (x = 0; x < ARRAY_LEN(perms); x++)
00466          ret |= perms[x].num;
00467       return ret;
00468    }
00469    return get_perm(string);
00470 }

static struct eventqent* unref_event ( struct eventqent e  )  [static, read]

Definition at line 820 of file manager.c.

References ast_atomic_fetchadd_int(), AST_LIST_NEXT, and eventqent::usecount.

Referenced by action_waitevent(), free_session(), and process_events().

00821 {
00822    ast_atomic_fetchadd_int(&e->usecount, -1);
00823    return AST_LIST_NEXT(e, eq_next);
00824 }


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 123 of file manager.c.

struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } [static]

Definition at line 960 of file manager.c.

Referenced by astman_append().

int block_sockets [static]

Definition at line 129 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 803 of file manager.c.

Referenced by __init_manager().

struct { ... } command_blacklist[] [static]

Referenced by check_blacklist().

int displayconnects = 1 [static]

Definition at line 122 of file manager.c.

int httptimeout = 60 [static]

Definition at line 125 of file manager.c.

int manager_debug [static]

enable some debugging code in the manager

Definition at line 132 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 126 of file manager.c.

struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } [static]

Definition at line 3296 of file manager.c.

Referenced by __manager_event().

char mandescr_atxfer[] [static]

Definition at line 2159 of file manager.c.

Referenced by __init_manager().

char mandescr_command[] [static]
Initial value:
"Description: Run a CLI command.\n"
"Variables: (Names marked with * are required)\n"
"  *Command: Asterisk CLI command to run\n"
"  ActionID: Optional Action id for message matching.\n"

Definition at line 2251 of file manager.c.

Referenced by __init_manager().

char mandescr_coresettings[] [static]
Initial value:
"Description: Query for Core PBX settings.\n"
"Variables: (Names marked with * are optional)\n"
"       *ActionID: ActionID of this transaction\n"

Definition at line 2703 of file manager.c.

Referenced by __init_manager().

char mandescr_coreshowchannels[] [static]
Initial value:
"Description: List currently defined channels and some information\n"
"             about them.\n"
"Variables:\n"
"          ActionID: Optional Action id for message matching.\n"

Definition at line 2806 of file manager.c.

Referenced by __init_manager().

char mandescr_corestatus[] [static]
Initial value:
"Description: Query for Core PBX status.\n"
"Variables: (Names marked with * are optional)\n"
"       *ActionID: ActionID of this transaction\n"

Definition at line 2749 of file manager.c.

Referenced by __init_manager().

char mandescr_createconfig[] [static]

Definition at line 1558 of file manager.c.

Referenced by __init_manager().

char mandescr_events[] [static]

Definition at line 1707 of file manager.c.

Referenced by __init_manager().

char mandescr_extensionstate[] [static]

Definition at line 2579 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfig[] [static]

Definition at line 1149 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfigjson[] [static]

Definition at line 1250 of file manager.c.

Referenced by __init_manager().

char mandescr_getvar[] [static]

Definition at line 1840 of file manager.c.

Referenced by __init_manager().

char mandescr_hangup[] [static]
Initial value:
"Description: Hangup a channel\n"
"Variables: \n"
"  Channel: The channel name to be hungup\n"

Definition at line 1772 of file manager.c.

Referenced by __init_manager().

char mandescr_listcategories[] [static]
Initial value:
"Description: A 'ListCategories' action will dump the categories in\n"
"a given file.\n"
"Variables:\n"
"   Filename: Configuration filename (e.g. foo.conf)\n"

Definition at line 1198 of file manager.c.

Referenced by __init_manager().

char mandescr_listcommands[] [static]
Initial value:
"Description: Returns the action name and synopsis for every\n"
"  action that is available to the user\n"
"Variables: NONE\n"

Definition at line 1685 of file manager.c.

Referenced by __init_manager().

char mandescr_logoff[] [static]
Initial value:
"Description: Logoff this manager session\n"
"Variables: NONE\n"

Definition at line 1730 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxcount[] [static]

Definition at line 2546 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 2518 of file manager.c.

Referenced by __init_manager().

char mandescr_modulecheck[] [static]

Definition at line 2875 of file manager.c.

Referenced by __init_manager().

char mandescr_moduleload[] [static]

Definition at line 2927 of file manager.c.

Referenced by __init_manager().

char mandescr_originate[] [static]

Definition at line 2376 of file manager.c.

Referenced by __init_manager().

char mandescr_ping[] [static]
Initial value:
"Description: A 'Ping' action will ellicit a 'Pong' response.  Used to keep the\n"
"  manager connection open.\n"
"Variables: NONE\n"

Manager PING.

Definition at line 1132 of file manager.c.

Referenced by __init_manager().

char mandescr_redirect[] [static]

Definition at line 2073 of file manager.c.

Referenced by __init_manager().

char mandescr_reload[] [static]
Initial value:
"Description: Send a reload event.\n"
"Variables: (Names marked with * are optional)\n"
"       *ActionID: ActionID of this transaction\n"
"       *Module: Name of the module to reload\n"

Definition at line 2787 of file manager.c.

Referenced by __init_manager().

char mandescr_sendtext[] [static]

Definition at line 2032 of file manager.c.

Referenced by __init_manager().

char mandescr_setvar[] [static]

Definition at line 1796 of file manager.c.

Referenced by __init_manager().

char mandescr_status[] [static]

Definition at line 1892 of file manager.c.

Referenced by __init_manager().

char mandescr_timeout[] [static]

Definition at line 2614 of file manager.c.

Referenced by __init_manager().

char mandescr_updateconfig[] [static]

Definition at line 1467 of file manager.c.

Referenced by __init_manager().

char mandescr_userevent[] [static]

Definition at line 2677 of file manager.c.

Referenced by __init_manager().

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1584 of file manager.c.

Referenced by __init_manager().

int num_sessions [static]

Definition at line 130 of file manager.c.

struct permalias perms[] [static]

helper functions to convert back and forth between string and numeric representation of set of flags

Referenced by authority_to_str(), get_perm(), and strings_to_mask().

int timestampevents [static]

Definition at line 124 of file manager.c.

struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static]

Definition at line 961 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 127 of file manager.c.

char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 145 of file manager.c.


Generated by  doxygen 1.6.2