Thu Apr 8 01:23:48 2010

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

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  mansession
struct  mansession_session
struct  permalias

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)
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)
static AST_LIST_HEAD_STATIC (sessions, mansession_session)
static AST_LIST_HEAD_STATIC (all_events, eventqent)
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.
static AST_RWLIST_HEAD_STATIC (manager_hooks, manager_custom_hook)
 list of hooks registered
static AST_RWLIST_HEAD_STATIC (actions, manager_action)
 list of actions registered
static AST_RWLIST_HEAD_STATIC (users, ast_manager_user)
 list of users found in the config file
 AST_THREADSTORAGE (manager_event_buf)
 AST_THREADSTORAGE (userevent_buf)
 AST_THREADSTORAGE (astman_append_buf)
 thread local buffer for astman_append
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 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 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 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 3272 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 }

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 3275 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_set(), ast_str_thread_get(), ast_tvnow(), authority_to_str(), buf, manager_custom_hook::helper, MANAGER_EVENT_BUF_INITSIZE, mansession_session::pending_event, eventqent::seq, ast_str::str, and mansession_session::waiting_thread.

03277 {
03278    struct mansession_session *session;
03279    struct manager_custom_hook *hook;
03280    struct ast_str *auth = ast_str_alloca(80);
03281    const char *cat_str;
03282    va_list ap;
03283    struct timeval now;
03284    struct ast_str *buf;
03285 
03286    /* Abort if there are neither any manager sessions nor hooks */
03287    if (!num_sessions && AST_RWLIST_EMPTY(&manager_hooks))
03288       return 0;
03289 
03290    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE)))
03291       return -1;
03292 
03293    cat_str = authority_to_str(category, &auth);
03294    ast_str_set(&buf, 0,
03295          "Event: %s\r\nPrivilege: %s\r\n",
03296           event, cat_str);
03297 
03298    if (timestampevents) {
03299       now = ast_tvnow();
03300       ast_str_append(&buf, 0,
03301             "Timestamp: %ld.%06lu\r\n",
03302              (long)now.tv_sec, (unsigned long) now.tv_usec);
03303    }
03304    if (manager_debug) {
03305       static int seq;
03306       ast_str_append(&buf, 0,
03307             "SequenceNumber: %d\r\n",
03308              ast_atomic_fetchadd_int(&seq, 1));
03309       ast_str_append(&buf, 0,
03310             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
03311    }
03312 
03313    va_start(ap, fmt);
03314    ast_str_append_va(&buf, 0, fmt, ap);
03315    va_end(ap);
03316 
03317    ast_str_append(&buf, 0, "\r\n");
03318 
03319    append_event(buf->str, category);
03320 
03321    /* Wake up any sleeping sessions */
03322    if (num_sessions) {
03323       AST_LIST_LOCK(&sessions);
03324       AST_LIST_TRAVERSE(&sessions, session, list) {
03325          ast_mutex_lock(&session->__lock);
03326          if (session->waiting_thread != AST_PTHREADT_NULL)
03327             pthread_kill(session->waiting_thread, SIGURG);
03328          else
03329             /* We have an event to process, but the mansession is
03330              * not waiting for it. We still need to indicate that there
03331              * is an event waiting so that get_input processes the pending
03332              * event instead of polling.
03333              */
03334             session->pending_event = 1;
03335          ast_mutex_unlock(&session->__lock);
03336       }
03337       AST_LIST_UNLOCK(&sessions);
03338    }
03339 
03340    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
03341       AST_RWLIST_RDLOCK(&manager_hooks);
03342       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
03343          hook->helper(category, event, buf->str);
03344       }
03345       AST_RWLIST_UNLOCK(&manager_hooks);
03346    }
03347 
03348    return 0;
03349 }

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

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

02151 {
02152    const char *name = astman_get_header(m, "Channel");
02153    const char *exten = astman_get_header(m, "Exten");
02154    const char *context = astman_get_header(m, "Context");
02155    struct ast_channel *chan = NULL;
02156    struct ast_call_feature *atxfer_feature = NULL;
02157    char *feature_code = NULL;
02158 
02159    if (ast_strlen_zero(name)) { 
02160       astman_send_error(s, m, "No channel specified");
02161       return 0;
02162    }
02163    if (ast_strlen_zero(exten)) {
02164       astman_send_error(s, m, "No extension specified");
02165       return 0;
02166    }
02167 
02168    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
02169       astman_send_error(s, m, "No attended transfer feature found");
02170       return 0;
02171    }
02172 
02173    if (!(chan = ast_get_channel_by_name_locked(name))) {
02174       astman_send_error(s, m, "Channel specified does not exist");
02175       return 0;
02176    }
02177 
02178    if (!ast_strlen_zero(context)) {
02179       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
02180    }
02181 
02182    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
02183       struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
02184       ast_queue_frame(chan, &f);
02185    }
02186 
02187    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
02188       struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
02189       ast_queue_frame(chan, &f);
02190    }
02191 
02192    astman_send_ack(s, m, "Atxfer successfully queued");
02193    ast_channel_unlock(chan);
02194 
02195    return 0;
02196 }

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

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

01738 {
01739    const char *authtype = astman_get_header(m, "AuthType");
01740 
01741    if (!strcasecmp(authtype, "MD5")) {
01742       if (ast_strlen_zero(s->session->challenge))
01743          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
01744       ast_mutex_lock(&s->session->__lock);
01745       astman_start_ack(s, m);
01746       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
01747       ast_mutex_unlock(&s->session->__lock);
01748    } else {
01749       astman_send_error(s, m, "Must specify AuthType");
01750    }
01751    return 0;
01752 }

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

Manager command "command" - execute CLI command.

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

02241 {
02242    const char *cmd = astman_get_header(m, "Command");
02243    const char *id = astman_get_header(m, "ActionID");
02244    char *buf, *final_buf;
02245    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
02246    int fd;
02247    off_t l;
02248 
02249    if (ast_strlen_zero(cmd)) {
02250       astman_send_error(s, m, "No command provided");
02251       return 0;
02252    }
02253 
02254    if (check_blacklist(cmd)) {
02255       astman_send_error(s, m, "Command blacklisted");
02256       return 0;
02257    }
02258 
02259    fd = mkstemp(template);
02260 
02261    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
02262    if (!ast_strlen_zero(id))
02263       astman_append(s, "ActionID: %s\r\n", id);
02264    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
02265    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
02266    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
02267 
02268    /* This has a potential to overflow the stack.  Hence, use the heap. */
02269    buf = ast_calloc(1, l + 1);
02270    final_buf = ast_calloc(1, l + 1);
02271    if (buf) {
02272       lseek(fd, 0, SEEK_SET);
02273       if (read(fd, buf, l) < 0) {
02274          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
02275       }
02276       buf[l] = '\0';
02277       if (final_buf) {
02278          term_strip(final_buf, buf, l);
02279          final_buf[l] = '\0';
02280       }
02281       astman_append(s, "%s", S_OR(final_buf, buf));
02282       ast_free(buf);
02283    }
02284    close(fd);
02285    unlink(template);
02286    astman_append(s, "--END COMMAND--\r\n\r\n");
02287    if (final_buf)
02288       ast_free(final_buf);
02289    return 0;
02290 }

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

Show PBX core settings information.

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

02692 {
02693    const char *actionid = astman_get_header(m, "ActionID");
02694    char idText[150];
02695 
02696    if (!ast_strlen_zero(actionid))
02697       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
02698    else
02699       idText[0] = '\0';
02700 
02701    astman_append(s, "Response: Success\r\n"
02702          "%s"
02703          "AMIversion: %s\r\n"
02704          "AsteriskVersion: %s\r\n"
02705          "SystemName: %s\r\n"
02706          "CoreMaxCalls: %d\r\n"
02707          "CoreMaxLoadAvg: %f\r\n"
02708          "CoreRunUser: %s\r\n"
02709          "CoreRunGroup: %s\r\n"
02710          "CoreMaxFilehandles: %d\r\n" 
02711          "CoreRealTimeEnabled: %s\r\n"
02712          "CoreCDRenabled: %s\r\n"
02713          "CoreHTTPenabled: %s\r\n"
02714          "\r\n",
02715          idText,
02716          AMI_VERSION,
02717          ast_get_version(), 
02718          ast_config_AST_SYSTEM_NAME,
02719          option_maxcalls,
02720          option_maxload,
02721          ast_config_AST_RUN_USER,
02722          ast_config_AST_RUN_GROUP,
02723          option_maxfiles,
02724          ast_realtime_enabled() ? "Yes" : "No",
02725          check_cdr_enabled() ? "Yes" : "No",
02726          check_webmanager_enabled() ? "Yes" : "No"
02727          );
02728    return 0;
02729 }

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

References ast_channel::_state, 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::priority, S_OR, and ast_cdr::start.

Referenced by __init_manager().

02797 {
02798    const char *actionid = astman_get_header(m, "ActionID");
02799    char actionidtext[256];
02800    struct ast_channel *c = NULL;
02801    int numchans = 0;
02802    int duration, durh, durm, durs;
02803 
02804    if (!ast_strlen_zero(actionid))
02805       snprintf(actionidtext, sizeof(actionidtext), "ActionID: %s\r\n", actionid);
02806    else
02807       actionidtext[0] = '\0';
02808 
02809    astman_send_listack(s, m, "Channels will follow", "start"); 
02810 
02811    while ((c = ast_channel_walk_locked(c)) != NULL) {
02812       struct ast_channel *bc = ast_bridged_channel(c);
02813       char durbuf[10] = "";
02814 
02815       if (c->cdr && !ast_tvzero(c->cdr->start)) {
02816          duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
02817          durh = duration / 3600;
02818          durm = (duration % 3600) / 60;
02819          durs = duration % 60;
02820          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
02821       }
02822 
02823       astman_append(s,
02824          "Event: CoreShowChannel\r\n"
02825          "Channel: %s\r\n"
02826          "UniqueID: %s\r\n"
02827          "Context: %s\r\n"
02828          "Extension: %s\r\n"
02829          "Priority: %d\r\n"
02830          "ChannelState: %d\r\n"
02831          "ChannelStateDesc: %s\r\n"
02832          "Application: %s\r\n"
02833          "ApplicationData: %s\r\n"
02834          "CallerIDnum: %s\r\n"
02835          "Duration: %s\r\n"
02836          "AccountCode: %s\r\n"
02837          "BridgedChannel: %s\r\n"
02838          "BridgedUniqueID: %s\r\n"
02839          "\r\n", c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, ast_state2str(c->_state),
02840          c->appl ? c->appl : "", c->data ? S_OR(c->data, ""): "",
02841          S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
02842       ast_channel_unlock(c);
02843       numchans++;
02844    }
02845 
02846    astman_append(s,
02847       "Event: CoreShowChannelsComplete\r\n"
02848       "EventList: Complete\r\n"
02849       "ListItems: %d\r\n"
02850       "%s"
02851       "\r\n", numchans, actionidtext);
02852 
02853    return 0;
02854 }

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

Show PBX core status information.

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

02738 {
02739    const char *actionid = astman_get_header(m, "ActionID");
02740    char idText[150];
02741    char startuptime[150];
02742    char reloadtime[150];
02743    struct ast_tm tm;
02744 
02745    if (!ast_strlen_zero(actionid))
02746       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
02747    else
02748       idText[0] = '\0';
02749 
02750    ast_localtime(&ast_startuptime, &tm, NULL);
02751    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
02752    ast_localtime(&ast_lastreloadtime, &tm, NULL);
02753    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
02754 
02755    astman_append(s, "Response: Success\r\n"
02756          "%s"
02757          "CoreStartupTime: %s\r\n"
02758          "CoreReloadTime: %s\r\n"
02759          "CoreCurrentCalls: %d\r\n"
02760          "\r\n",
02761          idText,
02762          startuptime,
02763          reloadtime,
02764          ast_active_channels()
02765          );
02766    return 0;
02767 }

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

Definition at line 1548 of file manager.c.

References ast_config_AST_CONFIG_DIR, AST_FILE_MODE, ast_str_alloca, ast_str_append(), ast_str_set(), astman_get_header(), astman_send_ack(), astman_send_error(), errno, and ast_str::str.

Referenced by __init_manager().

01549 {
01550    int fd;
01551    const char *fn = astman_get_header(m, "Filename");
01552    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
01553    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
01554    ast_str_append(&filepath, 0, "%s", fn);
01555 
01556    if ((fd = open(filepath->str, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
01557       close(fd);
01558       astman_send_ack(s, m, "New configuration file created successfully");
01559    } else 
01560       astman_send_error(s, m, strerror(errno));
01561 
01562    return 0;
01563 }

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

Definition at line 1697 of file manager.c.

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

Referenced by __init_manager().

01698 {
01699    const char *mask = astman_get_header(m, "EventMask");
01700    int res;
01701 
01702    res = set_eventmask(s, mask);
01703    if (res > 0)
01704       astman_append(s, "Response: Success\r\n"
01705              "Events: On\r\n\r\n");
01706    else if (res == 0)
01707       astman_append(s, "Response: Success\r\n"
01708              "Events: Off\r\n\r\n");
01709    return 0;
01710 }

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

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

02573 {
02574    const char *exten = astman_get_header(m, "Exten");
02575    const char *context = astman_get_header(m, "Context");
02576    char hint[256] = "";
02577    int status;
02578    if (ast_strlen_zero(exten)) {
02579       astman_send_error(s, m, "Extension not specified");
02580       return 0;
02581    }
02582    if (ast_strlen_zero(context))
02583       context = "default";
02584    status = ast_extension_state(NULL, context, exten);
02585    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
02586    astman_start_ack(s, m);
02587    astman_append(s,   "Message: Extension Status\r\n"
02588             "Exten: %s\r\n"
02589             "Context: %s\r\n"
02590             "Hint: %s\r\n"
02591             "Status: %d\r\n\r\n",
02592             exten, context, hint, status);
02593    return 0;
02594 }

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

Definition at line 1152 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, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

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

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

Definition at line 1246 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, json_escape(), ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

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

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

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

01830 {
01831    struct ast_channel *c = NULL;
01832    const char *name = astman_get_header(m, "Channel");
01833    const char *varname = astman_get_header(m, "Variable");
01834    char *varval;
01835    char workspace[1024] = "";
01836 
01837    if (ast_strlen_zero(varname)) {
01838       astman_send_error(s, m, "No variable specified");
01839       return 0;
01840    }
01841 
01842    if (!ast_strlen_zero(name)) {
01843       c = ast_get_channel_by_name_locked(name);
01844       if (!c) {
01845          astman_send_error(s, m, "No such channel");
01846          return 0;
01847       }
01848    }
01849 
01850    if (varname[strlen(varname) - 1] == ')') {
01851       if (!c) {
01852          c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/manager");
01853          if (c) {
01854             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
01855             ast_channel_free(c);
01856             c = NULL;
01857          } else
01858             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
01859       } else
01860          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
01861       varval = workspace;
01862    } else {
01863       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
01864    }
01865 
01866    if (c)
01867       ast_channel_unlock(c);
01868    astman_start_ack(s, m);
01869    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, varval);
01870 
01871    return 0;
01872 }

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

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

01760 {
01761    struct ast_channel *c = NULL;
01762    const char *name = astman_get_header(m, "Channel");
01763    if (ast_strlen_zero(name)) {
01764       astman_send_error(s, m, "No channel specified");
01765       return 0;
01766    }
01767    c = ast_get_channel_by_name_locked(name);
01768    if (!c) {
01769       astman_send_error(s, m, "No such channel");
01770       return 0;
01771    }
01772    ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
01773    ast_channel_unlock(c);
01774    astman_send_ack(s, m, "Channel Hungup");
01775    return 0;
01776 }

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

Definition at line 1196 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, and CONFIG_FLAG_WITHCOMMENTS.

Referenced by __init_manager().

01197 {
01198    struct ast_config *cfg;
01199    const char *fn = astman_get_header(m, "Filename");
01200    char *category = NULL;
01201    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
01202    int catcount = 0;
01203 
01204    if (ast_strlen_zero(fn)) {
01205       astman_send_error(s, m, "Filename not specified");
01206       return 0;
01207    }
01208    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
01209       astman_send_error(s, m, "Config file not found or file has invalid syntax");
01210       return 0;
01211    }
01212    astman_start_ack(s, m);
01213    while ((category = ast_category_browse(cfg, category))) {
01214       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
01215       catcount++;
01216    }
01217    if (catcount == 0) /* TODO: actually, a config with no categories doesn't even get loaded */
01218       astman_append(s, "Error: no categories found\r\n");
01219    ast_config_destroy(cfg);
01220    astman_append(s, "\r\n");
01221 
01222    return 0;
01223 }

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 1673 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().

01674 {
01675    struct manager_action *cur;
01676    struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */
01677 
01678    astman_start_ack(s, m);
01679    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01680       if (s->session->writeperm & cur->authority || cur->authority == 0)
01681          astman_append(s, "%s: %s (Priv: %s)\r\n",
01682             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
01683    }
01684    astman_append(s, "\r\n");
01685 
01686    return 0;
01687 }

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

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

01723 {
01724    if (authenticate(s, m)) {
01725       sleep(1);
01726       astman_send_error(s, m, "Authentication failed");
01727       return -1;
01728    }
01729    s->session->authenticated = 1;
01730    if (manager_displayconnects(s->session))
01731       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));
01732    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));
01733    astman_send_ack(s, m, "Authentication accepted");
01734    return 0;
01735 }

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

Definition at line 1716 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

01717 {
01718    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
01719    return -1;
01720 }

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

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

02541 {
02542    const char *mailbox = astman_get_header(m, "Mailbox");
02543    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
02544 
02545    if (ast_strlen_zero(mailbox)) {
02546       astman_send_error(s, m, "Mailbox not specified");
02547       return 0;
02548    }
02549    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
02550    astman_start_ack(s, m);
02551    astman_append(s,   "Message: Mailbox Message Count\r\n"
02552             "Mailbox: %s\r\n"
02553             "UrgMessages: %d\r\n"
02554             "NewMessages: %d\r\n"
02555             "OldMessages: %d\r\n"
02556             "\r\n",
02557             mailbox, urgentmsgs, newmsgs, oldmsgs);
02558    return 0;
02559 }

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

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

02512 {
02513    const char *mailbox = astman_get_header(m, "Mailbox");
02514    int ret;
02515 
02516    if (ast_strlen_zero(mailbox)) {
02517       astman_send_error(s, m, "Mailbox not specified");
02518       return 0;
02519    }
02520    ret = ast_app_has_voicemail(mailbox, NULL);
02521    astman_start_ack(s, m);
02522    astman_append(s, "Message: Mailbox Status\r\n"
02523           "Mailbox: %s\r\n"
02524           "Waiting: %d\r\n\r\n", mailbox, ret);
02525    return 0;
02526 }

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

Definition at line 2374 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, strcasestr(), fast_originate_helper::tech, fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

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

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

Definition at line 1137 of file manager.c.

References astman_append().

Referenced by __init_manager().

01138 {
01139    astman_append(s, "Response: Success\r\n"
01140       "Ping: Pong\r\n"
01141       "\r\n");
01142    return 0;
01143 }

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

action_redirect: The redirect manager command

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

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

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

Send a reload event.

Definition at line 2776 of file manager.c.

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

Referenced by __init_manager().

02777 {
02778    const char *module = astman_get_header(m, "Module");
02779    int res = ast_module_reload(S_OR(module, NULL));
02780 
02781    if (res == 2)
02782       astman_send_ack(s, m, "Module Reloaded");
02783    else
02784       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
02785    return 0;
02786 }

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

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

02022 {
02023    struct ast_channel *c = NULL;
02024    const char *name = astman_get_header(m, "Channel");
02025    const char *textmsg = astman_get_header(m, "Message");
02026    int res = 0;
02027 
02028    if (ast_strlen_zero(name)) {
02029       astman_send_error(s, m, "No channel specified");
02030       return 0;
02031    }
02032 
02033    if (ast_strlen_zero(textmsg)) {
02034       astman_send_error(s, m, "No Message specified");
02035       return 0;
02036    }
02037 
02038    c = ast_get_channel_by_name_locked(name);
02039    if (!c) {
02040       astman_send_error(s, m, "No such channel");
02041       return 0;
02042    }
02043 
02044    res = ast_sendtext(c, textmsg);
02045    ast_channel_unlock(c);
02046    
02047    if (res > 0)
02048       astman_send_ack(s, m, "Success");
02049    else
02050       astman_send_error(s, m, "Failure");
02051    
02052    return res;
02053 }

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

Definition at line 1785 of file manager.c.

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

Referenced by __init_manager().

01786 {
01787    struct ast_channel *c = NULL;
01788    const char *name = astman_get_header(m, "Channel");
01789    const char *varname = astman_get_header(m, "Variable");
01790    const char *varval = astman_get_header(m, "Value");
01791    int res = 0;
01792    
01793    if (ast_strlen_zero(varname)) {
01794       astman_send_error(s, m, "No variable specified");
01795       return 0;
01796    }
01797 
01798    if (!ast_strlen_zero(name)) {
01799       c = ast_get_channel_by_name_locked(name);
01800       if (!c) {
01801          astman_send_error(s, m, "No such channel");
01802          return 0;
01803       }
01804    }
01805    if (varname[strlen(varname)-1] == ')') {
01806       char *function = ast_strdupa(varname);
01807       res = ast_func_write(c, function, varval);
01808    } else {
01809       pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
01810    }
01811 
01812    if (c)
01813       ast_channel_unlock(c);
01814    if (res == 0) {
01815       astman_send_ack(s, m, "Variable Set"); 
01816    } else {
01817       astman_send_error(s, m, "Variable not set");
01818    }
01819    return 0;
01820 }

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

Manager "status" command to show channels.

Definition at line 1886 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, 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_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::cdr, channels, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, name, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_OR, ast_cdr::start, ast_str::str, and str.

Referenced by __init_manager().

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

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

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

02604 {
02605    struct ast_channel *c;
02606    const char *name = astman_get_header(m, "Channel");
02607    double timeout = atof(astman_get_header(m, "Timeout"));
02608    struct timeval when = { timeout, 0 };
02609 
02610    if (ast_strlen_zero(name)) {
02611       astman_send_error(s, m, "No channel specified");
02612       return 0;
02613    }
02614    if (!timeout || timeout < 0) {
02615       astman_send_error(s, m, "No timeout specified");
02616       return 0;
02617    }
02618    c = ast_get_channel_by_name_locked(name);
02619    if (!c) {
02620       astman_send_error(s, m, "No such channel");
02621       return 0;
02622    }
02623 
02624    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
02625    ast_channel_setwhentohangup_tv(c, when);
02626    ast_channel_unlock(c);
02627    astman_send_ack(s, m, "Timeout Set");
02628    return 0;
02629 }

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

Definition at line 1467 of file manager.c.

References ast_config_destroy(), ast_config_load2(), 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_text_file_save(), 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().

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

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

Definition at line 2666 of file manager.c.

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

Referenced by __init_manager().

02667 {
02668    const char *event = astman_get_header(m, "UserEvent");
02669    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
02670    int x;
02671 
02672    ast_str_reset(body);
02673 
02674    for (x = 0; x < m->hdrcount; x++) {
02675       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
02676          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
02677       }
02678    }
02679 
02680    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, body->str);
02681    astman_send_ack(s, m, "Event Sent");   
02682    return 0;
02683 }

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

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

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

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

Definition at line 3248 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::seq, and eventqent::usecount.

Referenced by __init_manager(), and __manager_event().

03249 {
03250    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
03251    static int seq;   /* sequence number */
03252 
03253    if (!tmp)
03254       return -1;
03255 
03256    /* need to init all fields, because ast_malloc() does not */
03257    tmp->usecount = 0;
03258    tmp->category = category;
03259    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
03260    AST_LIST_NEXT(tmp, eq_next) = NULL;
03261    strcpy(tmp->eventdata, str);
03262 
03263    AST_LIST_LOCK(&all_events);
03264    AST_LIST_INSERT_TAIL(&all_events, tmp, eq_next);
03265    AST_LIST_UNLOCK(&all_events);
03266 
03267    return 0;
03268 }

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.

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 }

static AST_LIST_HEAD_STATIC ( sessions  ,
mansession_session   
) [static]
static AST_LIST_HEAD_STATIC ( all_events  ,
eventqent   
) [static]
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 3423 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().

03424 {
03425    struct manager_action *cur = NULL;
03426 
03427    if (!(cur = ast_calloc(1, sizeof(*cur))))
03428       return -1;
03429 
03430    cur->action = action;
03431    cur->authority = auth;
03432    cur->func = func;
03433    cur->synopsis = synopsis;
03434    cur->description = description;
03435 
03436    if (ast_manager_register_struct(cur)) {
03437       ast_free(cur);
03438       return -1;
03439    }
03440 
03441    return 0;
03442 }

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 3387 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().

03388 {
03389    struct manager_action *cur, *prev = NULL;
03390    struct timespec tv = { 5, };
03391 
03392    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03393       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03394       return -1;
03395    }
03396    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03397       int ret = strcasecmp(cur->action, act->action);
03398       if (ret == 0) {
03399          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
03400          AST_RWLIST_UNLOCK(&actions);
03401          return -1;
03402       }
03403       if (ret > 0) { /* Insert these alphabetically */
03404          prev = cur;
03405          break;
03406       }
03407    }
03408 
03409    if (prev)
03410       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
03411    else
03412       AST_RWLIST_INSERT_HEAD(&actions, act, list);
03413 
03414    ast_verb(2, "Manager registered action %s\n", act->action);
03415 
03416    AST_RWLIST_UNLOCK(&actions);
03417 
03418    return 0;
03419 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

03355 {
03356    struct manager_action *cur;
03357    struct timespec tv = { 5, };
03358 
03359    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03360       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03361       return -1;
03362    }
03363    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
03364       if (!strcasecmp(action, cur->action)) {
03365          AST_RWLIST_REMOVE_CURRENT(list);
03366          ast_free(cur);
03367          ast_verb(2, "Manager unregistered action %s\n", action);
03368          break;
03369       }
03370    }
03371    AST_RWLIST_TRAVERSE_SAFE_END;
03372    AST_RWLIST_UNLOCK(&actions);
03373 
03374    return 0;
03375 }

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 }

static AST_RWLIST_HEAD_STATIC ( manager_hooks  ,
manager_custom_hook   
) [static]

list of hooks registered

static AST_RWLIST_HEAD_STATIC ( actions  ,
manager_action   
) [static]

list of actions registered

static AST_RWLIST_HEAD_STATIC ( users  ,
ast_manager_user   
) [static]

list of users found in the config file

AST_THREADSTORAGE ( manager_event_buf   ) 
AST_THREADSTORAGE ( userevent_buf   ) 
AST_THREADSTORAGE ( astman_append_buf   ) 

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.
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_set_va(), ast_str_thread_get(), ast_verbose, ASTMAN_APPEND_BUF_INITSIZE, buf, mansession_session::f, mansession::f, send_string(), mansession::session, and ast_str::str.

Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), 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_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(), 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, buf->str);
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(), 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_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_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_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(), 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_strdupa, ast_strlen_zero(), ast_variable_new(), message::hdrcount, message::headers, parse(), strsep(), 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_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), 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 
)

Send ack in manager list transaction.

Definition at line 1042 of file manager.c.

References astman_send_response_full().

Referenced by action_coreshowchannels(), action_meetmelist(), manager_dpsendack(), manager_show_registry(), and manager_sip_show_peers().

01043 {
01044    astman_send_response_full(s, m, "Success", msg, listflag);
01045 }

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(), 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    (*res)->used = 0;
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 ((*res)->used == 0)  /* replace empty string with something sensible */
00403       ast_str_append(res, 0, "<none>");
00404 
00405    return (*res)->str;
00406 }

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

Definition at line 2198 of file manager.c.

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

Referenced by action_command().

02199 {
02200    char *cmd_copy, *cur_cmd;
02201    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
02202    int i;
02203 
02204    cmd_copy = ast_strdupa(cmd);
02205    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
02206       cur_cmd = ast_strip(cur_cmd);
02207       if (ast_strlen_zero(cur_cmd)) {
02208          i--;
02209          continue;
02210       }
02211 
02212       cmd_words[i] = cur_cmd;
02213    }
02214 
02215    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
02216       int j, match = 1;
02217 
02218       for (j = 0; command_blacklist[i].words[j]; j++) {
02219          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
02220             match = 0;
02221             break;
02222          }
02223       }
02224 
02225       if (match) {
02226          return 1;
02227       }
02228    }
02229 
02230    return 0;
02231 }

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

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

Referenced by session_do().

03113 {
03114    struct message m = { 0 };
03115    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
03116    int res;
03117 
03118    for (;;) {
03119       /* Check if any events are pending and do them if needed */
03120       if (process_events(s))
03121          return -1;
03122       res = get_input(s, header_buf);
03123       if (res == 0) {
03124          continue;
03125       } else if (res > 0) {
03126          if (ast_strlen_zero(header_buf))
03127             return process_message(s, &m) ? -1 : 0;
03128          else if (m.hdrcount < (AST_MAX_MANHEADERS - 1))
03129             m.headers[m.hdrcount++] = ast_strdupa(header_buf);
03130       } else {
03131          return res;
03132       }
03133    }
03134 }

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

Definition at line 2311 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, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.

Referenced by action_originate().

02312 {
02313    struct fast_originate_helper *in = data;
02314    int res;
02315    int reason = 0;
02316    struct ast_channel *chan = NULL;
02317    char requested_channel[AST_CHANNEL_NAME];
02318 
02319    if (!ast_strlen_zero(in->app)) {
02320       res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
02321          S_OR(in->cid_num, NULL),
02322          S_OR(in->cid_name, NULL),
02323          in->vars, in->account, &chan);
02324    } else {
02325       res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
02326          S_OR(in->cid_num, NULL),
02327          S_OR(in->cid_name, NULL),
02328          in->vars, in->account, &chan);
02329    }
02330 
02331    if (!chan)
02332       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);   
02333    /* Tell the manager what happened with the channel */
02334    manager_event(EVENT_FLAG_CALL, "OriginateResponse",
02335       "%s%s"
02336       "Response: %s\r\n"
02337       "Channel: %s\r\n"
02338       "Context: %s\r\n"
02339       "Exten: %s\r\n"
02340       "Reason: %d\r\n"
02341       "Uniqueid: %s\r\n"
02342       "CallerIDNum: %s\r\n"
02343       "CallerIDName: %s\r\n",
02344       in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success", 
02345       chan ? chan->name : requested_channel, in->context, in->exten, reason, 
02346       chan ? chan->uniqueid : "<null>",
02347       S_OR(in->cid_num, "<unknown>"),
02348       S_OR(in->cid_name, "<unknown>")
02349       );
02350 
02351    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
02352    if (chan)
02353       ast_channel_unlock(chan);
02354    ast_free(in);
02355    return NULL;
02356 }

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::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 3042 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().

03043 {
03044    int res, x;
03045    int maxlen = sizeof(s->session->inbuf) - 1;
03046    char *src = s->session->inbuf;
03047 
03048    /*
03049     * Look for \r\n within the buffer. If found, copy to the output
03050     * buffer and return, trimming the \r\n (not used afterwards).
03051     */
03052    for (x = 0; x < s->session->inlen; x++) {
03053       int cr;  /* set if we have \r */
03054       if (src[x] == '\r' && x+1 < s->session->inlen && src[x+1] == '\n')
03055          cr = 2;  /* Found. Update length to include \r\n */
03056       else if (src[x] == '\n')
03057          cr = 1;  /* also accept \n only */
03058       else
03059          continue;
03060       memmove(output, src, x);   /*... but trim \r\n */
03061       output[x] = '\0';    /* terminate the string */
03062       x += cr;       /* number of bytes used */
03063       s->session->inlen -= x;       /* remaining size */
03064       memmove(src, src + x, s->session->inlen); /* remove used bytes */
03065       return 1;
03066    }
03067    if (s->session->inlen >= maxlen) {
03068       /* no crlf found, and buffer full - sorry, too long for us */
03069       ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
03070       s->session->inlen = 0;
03071    }
03072    res = 0;
03073    while (res == 0) {
03074       /* XXX do we really need this locking ? */
03075       ast_mutex_lock(&s->session->__lock);
03076       if (s->session->pending_event) {
03077          s->session->pending_event = 0;
03078          ast_mutex_unlock(&s->session->__lock);
03079          return 0;
03080       }
03081       s->session->waiting_thread = pthread_self();
03082       ast_mutex_unlock(&s->session->__lock);
03083 
03084       res = ast_wait_for_input(s->session->fd, -1);   /* return 0 on timeout ? */
03085 
03086       ast_mutex_lock(&s->session->__lock);
03087       s->session->waiting_thread = AST_PTHREADT_NULL;
03088       ast_mutex_unlock(&s->session->__lock);
03089    }
03090    if (res < 0) {
03091       /* If we get a signal from some other thread (typically because
03092        * there are new events queued), return 0 to notify the caller.
03093        */
03094       if (errno == EINTR || errno == EAGAIN)
03095          return 0;
03096       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
03097       return -1;
03098    }
03099    ast_mutex_lock(&s->session->__lock);
03100    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
03101    if (res < 1)
03102       res = -1;   /* error return */
03103    else {
03104       s->session->inlen += res;
03105       src[s->session->inlen] = '\0';
03106       res = 0;
03107    }
03108    ast_mutex_unlock(&s->session->__lock);
03109    return res;
03110 }

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, 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 debug [on|off]";
00570       e->usage = "Usage: manager 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 == 2)
00576       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
00577    else if (a->argc == 3) {
00578       if (!strcasecmp(a->argv[2], "on"))
00579          manager_debug = 1;
00580       else if (!strcasecmp(a->argv[2], "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_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::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, 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 1310 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().

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

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

Referenced by action_getconfigjson().

01230 {
01231    for (; *in; in++) {
01232       if (*in == '\\' || *in == '\"')
01233          *out++ = '\\';
01234       *out++ = *in;
01235    }
01236    *out = '\0';
01237 }

static int manager_displayconnects ( struct mansession_session session  )  [static]

Get displayconnects config option.

Parameters:
s 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 2866 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().

02867 {
02868    int res;
02869    const char *module = astman_get_header(m, "Module");
02870    const char *id = astman_get_header(m, "ActionID");
02871    char idText[256];
02872 #if !defined(LOW_MEMORY)
02873    const char *version;
02874 #endif
02875    char filename[PATH_MAX];
02876    char *cut;
02877 
02878    ast_copy_string(filename, module, sizeof(filename));
02879    if ((cut = strchr(filename, '.'))) {
02880       *cut = '\0';
02881    } else {
02882       cut = filename + strlen(filename);
02883    }
02884    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
02885    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
02886    res = ast_module_check(filename);
02887    if (!res) {
02888       astman_send_error(s, m, "Module not loaded");
02889       return 0;
02890    }
02891    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
02892    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
02893 #if !defined(LOW_MEMORY)
02894    version = ast_file_version_find(filename);
02895 #endif
02896 
02897    if (!ast_strlen_zero(id))
02898       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02899    else
02900       idText[0] = '\0';
02901    astman_append(s, "Response: Success\r\n%s", idText);
02902 #if !defined(LOW_MEMORY)
02903    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
02904 #endif
02905    return 0;
02906 }

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

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

02920 {
02921    int res;
02922    const char *module = astman_get_header(m, "Module");
02923    const char *loadtype = astman_get_header(m, "LoadType");
02924 
02925    if (!loadtype || strlen(loadtype) == 0)
02926       astman_send_error(s, m, "Incomplete ModuleLoad action.");
02927    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0)
02928       astman_send_error(s, m, "Need module name");
02929 
02930    if (!strcasecmp(loadtype, "load")) {
02931       res = ast_load_resource(module);
02932       if (res)
02933          astman_send_error(s, m, "Could not load module.");
02934       else
02935          astman_send_ack(s, m, "Module loaded.");
02936    } else if (!strcasecmp(loadtype, "unload")) {
02937       res = ast_unload_resource(module, AST_FORCE_SOFT);
02938       if (res)
02939          astman_send_error(s, m, "Could not unload module.");
02940       else
02941          astman_send_ack(s, m, "Module unloaded.");
02942    } else if (!strcasecmp(loadtype, "reload")) {
02943       if (module != NULL) {
02944          res = ast_module_reload(module);
02945          if (res == 0)
02946             astman_send_error(s, m, "No such module.");
02947          else if (res == 1)
02948             astman_send_error(s, m, "Module does not support reload action.");
02949          else
02950             astman_send_ack(s, m, "Module reloaded.");
02951       } else {
02952          ast_module_reload(NULL);   /* Reload all modules */
02953          astman_send_ack(s, m, "All modules reloaded");
02954       }
02955    } else 
02956       astman_send_error(s, m, "Incomplete ModuleLoad action.");
02957    return 0;
02958 }

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

Definition at line 3377 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

03378 {
03379    /* Notify managers of change */
03380    char hint[512];
03381    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
03382 
03383    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
03384    return 0;
03385 }

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

References mansession_session::__lock, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::authenticated, eventqent::category, 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().

02637 {
02638    int ret = 0;
02639 
02640    ast_mutex_lock(&s->session->__lock);
02641    if (s->session->f != NULL) {
02642       struct eventqent *eqe;
02643 
02644       while ( (eqe = NEW_EVENT(s)) ) {
02645          ref_event(eqe);
02646          if (!ret && s->session->authenticated &&
02647              (s->session->readperm & eqe->category) == eqe->category &&
02648              (s->session->send_events & eqe->category) == eqe->category) {
02649             if (send_string(s, eqe->eventdata) < 0)
02650                ret = -1;   /* don't send more */
02651          }
02652          s->session->last_ev = unref_event(s->session->last_ev);
02653       }
02654    }
02655    ast_mutex_unlock(&s->session->__lock);
02656    return ret;
02657 }

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

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

02974 {
02975    char action[80] = "";
02976    int ret = 0;
02977    struct manager_action *tmp;
02978    const char *user = astman_get_header(m, "Username");
02979 
02980    ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));
02981    ast_debug(1, "Manager received command '%s'\n", action);
02982 
02983    if (ast_strlen_zero(action)) {
02984       ast_mutex_lock(&s->session->__lock);
02985       astman_send_error(s, m, "Missing action in request");
02986       ast_mutex_unlock(&s->session->__lock);
02987       return 0;
02988    }
02989 
02990    if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
02991       ast_mutex_lock(&s->session->__lock);
02992       astman_send_error(s, m, "Permission denied");
02993       ast_mutex_unlock(&s->session->__lock);
02994       return 0;
02995    }
02996 
02997    if (!allowmultiplelogin && !s->session->authenticated && user &&
02998       (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
02999       if (check_manager_session_inuse(user)) {
03000          sleep(1);
03001          ast_mutex_lock(&s->session->__lock);
03002          astman_send_error(s, m, "Login Already In Use");
03003          ast_mutex_unlock(&s->session->__lock);
03004          return -1;
03005       }
03006    }
03007 
03008    AST_RWLIST_RDLOCK(&actions);
03009    AST_RWLIST_TRAVERSE(&actions, tmp, list) {
03010       if (strcasecmp(action, tmp->action))
03011          continue;
03012       if (s->session->writeperm & tmp->authority || tmp->authority == 0)
03013          ret = tmp->func(s, m);
03014       else
03015          astman_send_error(s, m, "Permission denied");
03016       break;
03017    }
03018    AST_RWLIST_UNLOCK(&actions);
03019 
03020    if (!tmp) {
03021       char buf[512];
03022       snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
03023       ast_mutex_lock(&s->session->__lock);
03024       astman_send_error(s, m, buf);
03025       ast_mutex_unlock(&s->session->__lock);
03026    }
03027    if (ret)
03028       return ret;
03029    /* Once done with our message, deliver any pending events */
03030    return process_events(s);
03031 }

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 3221 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().

03222 {
03223    struct mansession_session *session;
03224    time_t now = time(NULL);
03225 
03226    AST_LIST_LOCK(&sessions);
03227    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, session, list) {
03228       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
03229          AST_LIST_REMOVE_CURRENT(list);
03230          ast_atomic_fetchadd_int(&num_sessions, -1);
03231          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
03232             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
03233                session->username, ast_inet_ntoa(session->sin.sin_addr));
03234          }
03235          free_session(session);  /* XXX outside ? */
03236          if (--n_max <= 0)
03237             break;
03238       }
03239    }
03240    AST_LIST_TRAVERSE_SAFE_END;
03241    AST_LIST_UNLOCK(&sessions);
03242 }

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 3144 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, 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.

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

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.

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.

char mandescr_atxfer[] [static]

Definition at line 2141 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 2233 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 2685 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 2788 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 2731 of file manager.c.

Referenced by __init_manager().

char mandescr_createconfig[] [static]

Definition at line 1541 of file manager.c.

Referenced by __init_manager().

char mandescr_events[] [static]

Definition at line 1689 of file manager.c.

Referenced by __init_manager().

char mandescr_extensionstate[] [static]

Definition at line 2561 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfig[] [static]

Definition at line 1145 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfigjson[] [static]

Definition at line 1239 of file manager.c.

Referenced by __init_manager().

char mandescr_getvar[] [static]

Definition at line 1822 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 1754 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 1190 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 1667 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 1712 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxcount[] [static]

Definition at line 2528 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 2500 of file manager.c.

Referenced by __init_manager().

char mandescr_modulecheck[] [static]

Definition at line 2856 of file manager.c.

Referenced by __init_manager().

char mandescr_moduleload[] [static]

Definition at line 2908 of file manager.c.

Referenced by __init_manager().

char mandescr_originate[] [static]

Definition at line 2358 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 2055 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 2769 of file manager.c.

Referenced by __init_manager().

char mandescr_sendtext[] [static]

Definition at line 2014 of file manager.c.

Referenced by __init_manager().

char mandescr_setvar[] [static]

Definition at line 1778 of file manager.c.

Referenced by __init_manager().

char mandescr_status[] [static]

Definition at line 1874 of file manager.c.

Referenced by __init_manager().

char mandescr_timeout[] [static]

Definition at line 2596 of file manager.c.

Referenced by __init_manager().

char mandescr_updateconfig[] [static]

Definition at line 1453 of file manager.c.

Referenced by __init_manager().

char mandescr_userevent[] [static]

Definition at line 2659 of file manager.c.

Referenced by __init_manager().

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1566 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.

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 on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1