Wed Aug 18 22:34:35 2010

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

callback to display queues status in manager


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 965 of file manager.c.

Referenced by astman_append().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 868 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 869 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 870 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

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

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

Definition at line 1005 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 225 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 871 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().

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

static void __init_astman_append_buf ( void   )  [static]

thread local buffer for astman_append

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

Definition at line 961 of file manager.c.

00971 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 3293 of file manager.c.

03296 : Send AMI event to client */

static void __init_userevent_buf ( void   )  [static]

Definition at line 962 of file manager.c.

00971 {

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 3297 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, MANAGER_EVENT_BUF_INITSIZE, mansession_session::pending_event, seq, and mansession_session::waiting_thread.

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

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

Definition at line 2172 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, f, name, pbx_builtin_setvar_helper(), and s.

Referenced by __init_manager().

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

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

Definition at line 1759 of file manager.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and s.

Referenced by __init_manager().

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

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

Manager command "command" - execute CLI command.

Definition at line 2262 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, S_OR, and term_strip().

Referenced by __init_manager().

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

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

Show PBX core settings information.

Definition at line 2713 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, option_maxload, and s.

Referenced by __init_manager().

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

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

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

Referenced by __init_manager().

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

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

Show PBX core status information.

Definition at line 2759 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1549 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, s, and ast_str::str.

Referenced by __init_manager().

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

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

Definition at line 1698 of file manager.c.

References ARRAY_LEN, astman_append(), astman_get_header(), astman_send_error(), num, perms, s, and set_eventmask().

Referenced by __init_manager().

01699 {
01700    const char *mask = astman_get_header(m, "EventMask");
01701    int res, x;
01702 
01703    res = set_eventmask(s, mask);
01704    if (broken_events_action) {
01705       /* if this option is set we should not return a response on
01706        * error, or when all events are set */
01707 
01708       if (res > 0) {
01709          for (x = 0; x < ARRAY_LEN(perms); x++) {
01710             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
01711                return 0;
01712             }
01713          }
01714          astman_append(s, "Response: Success\r\n"
01715                 "Events: On\r\n\r\n");
01716       } else if (res == 0)
01717          astman_append(s, "Response: Success\r\n"
01718                 "Events: Off\r\n\r\n");
01719       return 0;
01720    }
01721 
01722    if (res > 0)
01723       astman_append(s, "Response: Success\r\n"
01724              "Events: On\r\n\r\n");
01725    else if (res == 0)
01726       astman_append(s, "Response: Success\r\n"
01727              "Events: Off\r\n\r\n");
01728    else
01729       astman_send_error(s, m, "Invalid event mask");
01730 
01731    return 0;
01732 }

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

Definition at line 2594 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(), s, and status.

Referenced by __init_manager().

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

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

Definition at line 1153 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1247 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1851 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, pbx_retrieve_variable(), and s.

Referenced by __init_manager().

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

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

Definition at line 1781 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(), name, and s.

Referenced by __init_manager().

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

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

Definition at line 1197 of file manager.c.

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

Referenced by __init_manager().

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

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 1674 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(), s, and manager_action::synopsis.

Referenced by __init_manager().

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

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

Definition at line 1744 of file manager.c.

References ast_inet_ntoa(), ast_log(), ast_verb, astman_send_ack(), astman_send_error(), authenticate(), LOG_EVENT, manager_displayconnects(), and s.

Referenced by __init_manager().

01745 {
01746    if (authenticate(s, m)) {
01747       sleep(1);
01748       astman_send_error(s, m, "Authentication failed");
01749       return -1;
01750    }
01751    s->session->authenticated = 1;
01752    if (manager_displayconnects(s->session))
01753       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));
01754    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));
01755    astman_send_ack(s, m, "Authentication accepted");
01756    return 0;
01757 }

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

Definition at line 1738 of file manager.c.

References astman_send_response(), and s.

Referenced by __init_manager().

01739 {
01740    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
01741    return -1;
01742 }

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

Definition at line 2562 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2533 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2396 of file manager.c.

References app, 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(), ast_frame::data, EVENT_FLAG_SYSTEM, fast_originate(), format, s, and strcasestr().

Referenced by __init_manager().

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

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

Definition at line 1138 of file manager.c.

References astman_append(), and s.

Referenced by __init_manager().

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

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

action_redirect: The redirect manager command

Definition at line 2088 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, ast_channel::priority, and s.

Referenced by __init_manager().

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

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

Send a reload event.

Definition at line 2798 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2043 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(), name, and s.

Referenced by __init_manager().

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

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

Definition at line 1807 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(), s, and S_OR.

Referenced by __init_manager().

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

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

Manager "status" command to show channels.

Definition at line 1908 of file manager.c.

References AST_APP_ARG, ast_channel_walk_locked(), AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), ast_get_channel_by_name_locked(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::name, name, pbx_retrieve_variable(), s, S_OR, and str.

Referenced by __init_manager().

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

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

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

Referenced by __init_manager().

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

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

Definition at line 1468 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_flags, config_text_file_save(), FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, handle_updates(), s, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.

Referenced by __init_manager().

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

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

Definition at line 2688 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, s, ast_str::str, and userevent_buf.

Referenced by __init_manager().

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

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

Definition at line 1574 of file manager.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_strlen_zero(), ast_wait_for_input(), astman_get_header(), NEW_EVENT, and s.

Referenced by __init_manager().

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

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

Definition at line 3270 of file manager.c.

References ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, ast_malloc, and seq.

Referenced by __init_manager(), and __manager_event().

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

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

References eventqent::next.

Referenced by get_perm().

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

int ast_manager_register2 ( const char *  action,
int  authority,
int(*)(struct mansession *s, const struct message *m)  func,
const char *  synopsis,
const char *  description 
)

Register a manager command with the manager interface.

Parameters:
action Name of the requested Action:
authority Required authority for this command
func Function to call for this command
synopsis Help text (one line, up to 30 chars) for CLI manager show commands
description Help text, several lines

Definition at line 3445 of file manager.c.

References ast_calloc, ast_free, and ast_manager_register_struct().

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

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

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

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

static int ast_manager_register_struct ( struct manager_action act  )  [static]

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

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

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

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

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

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

utility functions for creating AMI replies

Definition at line 970 of file manager.c.

References ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, buf, s, and send_string().

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

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

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

Get header from mananger transaction.

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

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

struct ast_variable* astman_get_variables ( const struct message m  ) 

Get a linked list of the Variable: headers.

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

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

void astman_send_ack ( struct mansession s,
const struct message m,
char *  msg 
)

Send ack in manager transaction.

Definition at line 1033 of file manager.c.

References astman_send_response_full(), and s.

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_atxfer(), action_bridge(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_hangup(), action_login(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peers(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_sipnotify(), meetmemute(), start_monitor_action(), and stop_monitor_action().

01034 {
01035    astman_send_response_full(s, m, "Success", msg, NULL);
01036 }

void astman_send_error ( struct mansession s,
const struct message m,
char *  error 
)

Send error in manager transaction.

Definition at line 1028 of file manager.c.

References astman_send_response_full(), and s.

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_events(), 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(), start_monitor_action(), and stop_monitor_action().

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

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

Send ack in manager list transaction.

Definition at line 1043 of file manager.c.

References astman_send_response_full(), and s.

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

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

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

Send response in manager transaction.

Definition at line 1023 of file manager.c.

References astman_send_response_full(), and s.

Referenced by action_logoff().

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

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

Definition at line 1006 of file manager.c.

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

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

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

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

Definition at line 1038 of file manager.c.

References astman_send_response_full(), MSG_MOREDATA, and s.

Referenced by action_challenge(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), and action_mailboxstatus().

01039 {
01040    astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
01041 }

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

Definition at line 1072 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(), get_manager_by_name_locked(), len(), LOG_NOTICE, md5(), MD5Final(), MD5Init(), MD5Update(), s, S_OR, set_eventmask(), and user.

Referenced by action_login(), authenticate_reply(), and registry_rerequest().

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

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

Convert authority code to a list of options.

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

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

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

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

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

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 317 of file manager.c.

Referenced by handle_show_settings().

00318 {
00319    return manager_enabled;
00320 }

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

Definition at line 473 of file manager.c.

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

Referenced by process_message().

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

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 322 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

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

static void destroy_session ( struct mansession_session session  )  [static]

Definition at line 853 of file manager.c.

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

Referenced by accept_thread(), and skinny_session().

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

static int do_message ( struct mansession s  )  [static]

Definition at line 3134 of file manager.c.

References AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), get_input(), message::hdrcount, message::headers, process_events(), process_message(), and s.

Referenced by session_do().

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

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

Definition at line 2333 of file manager.c.

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

Referenced by action_originate().

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

static void free_session ( struct mansession_session session  )  [static]

Definition at line 835 of file manager.c.

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

Referenced by destroy_session(), and purge_sessions().

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

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

References ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_wait_for_input(), errno, LOG_WARNING, s, and ast_frame::src.

Referenced by do_message(), and skinny_session().

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

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

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

Definition at line 492 of file manager.c.

References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.

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

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

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

Definition at line 431 of file manager.c.

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

Referenced by strings_to_mask().

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

static struct eventqent* grab_last ( void   )  [static]

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

Definition at line 331 of file manager.c.

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

Referenced by session_do().

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

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 785 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.

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

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

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

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

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

Definition at line 589 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_cli_args::fd, get_manager_by_name_locked(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, user, and ast_cli_args::word.

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

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

Definition at line 652 of file manager.c.

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

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

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

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

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

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 696 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.

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

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

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

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

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

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

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

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

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

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

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

Referenced by action_getconfigjson().

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

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

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

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

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

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

Definition at line 2888 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, s, and version.

Referenced by __init_manager().

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

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

Definition at line 2941 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 3399 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

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

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

References ast_mutex_lock(), ast_mutex_unlock(), NEW_EVENT, ref_event(), s, send_string(), and unref_event().

Referenced by do_message(), and process_message().

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

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

Definition at line 2995 of file manager.c.

References __astman_get_header(), 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(), manager_action::authority, buf, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, process_events(), and s.

Referenced by do_message().

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

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

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

Referenced by purge_old_stuff().

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

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

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

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

static void ref_event ( struct eventqent e  )  [static]

Definition at line 827 of file manager.c.

References ast_atomic_fetchadd_int(), and eventqent::usecount.

Referenced by process_events().

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

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

References ast_careful_fwrite(), and s.

Referenced by astman_append(), and process_events().

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

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

References AMI_VERSION, 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(), do_message(), ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), LOG_EVENT, manager_displayconnects(), ast_tcptls_session_instance::remote_address, and s.

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

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

References ast_mutex_lock(), ast_mutex_unlock(), s, and strings_to_mask().

Referenced by action_events(), and authenticate().

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

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

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

Referenced by set_eventmask().

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

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

Definition at line 821 of file manager.c.

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

Referenced by free_session(), and process_events().

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


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 123 of file manager.c.

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

Definition at line 961 of file manager.c.

Referenced by astman_append().

int block_sockets [static]

Definition at line 130 of file manager.c.

int broken_events_action = 0 [static]

Definition at line 126 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 804 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 133 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 127 of file manager.c.

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

Definition at line 3293 of file manager.c.

Referenced by __manager_event().

char mandescr_atxfer[] [static]

Definition at line 2163 of file manager.c.

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

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

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

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

char mandescr_createconfig[] [static]

Definition at line 1542 of file manager.c.

Referenced by __init_manager().

char mandescr_events[] [static]

Definition at line 1690 of file manager.c.

char mandescr_extensionstate[] [static]

Definition at line 2583 of file manager.c.

char mandescr_getconfig[] [static]

Definition at line 1146 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfigjson[] [static]

Definition at line 1240 of file manager.c.

Referenced by __init_manager().

char mandescr_getvar[] [static]

Definition at line 1844 of file manager.c.

char mandescr_hangup[] [static]

Initial value:

"Description: Hangup a channel\n"
"Variables: \n"
"  Channel: The channel name to be hungup\n"

Definition at line 1776 of file manager.c.

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

char mandescr_logoff[] [static]

Initial value:

"Description: Logoff this manager session\n"
"Variables: NONE\n"

Definition at line 1734 of file manager.c.

char mandescr_mailboxcount[] [static]

Definition at line 2550 of file manager.c.

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 2522 of file manager.c.

char mandescr_modulecheck[] [static]

Definition at line 2878 of file manager.c.

char mandescr_moduleload[] [static]

Definition at line 2930 of file manager.c.

char mandescr_originate[] [static]

Definition at line 2380 of file manager.c.

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

Referenced by __init_manager().

char mandescr_redirect[] [static]

Definition at line 2077 of file manager.c.

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

char mandescr_sendtext[] [static]

Definition at line 2036 of file manager.c.

char mandescr_setvar[] [static]

Definition at line 1800 of file manager.c.

char mandescr_status[] [static]

Definition at line 1896 of file manager.c.

char mandescr_timeout[] [static]

Definition at line 2618 of file manager.c.

char mandescr_updateconfig[] [static]

Definition at line 1454 of file manager.c.

Referenced by __init_manager().

char mandescr_userevent[] [static]

Definition at line 2681 of file manager.c.

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1567 of file manager.c.

Referenced by __init_manager().

int num_sessions [static]

Definition at line 131 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 action_events(), authority_to_str(), get_perm(), and strings_to_mask().

int timestampevents [static]

Definition at line 124 of file manager.c.

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

Definition at line 962 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 128 of file manager.c.

char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 146 of file manager.c.


Generated on Wed Aug 18 22:34:36 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7