Wed Oct 28 11:53:24 2009

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

Variables

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

Detailed Description

callback to display queues status in manager

callback to display list of locally configured nodes


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 964 of file manager.c.

Referenced by astman_append().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 867 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 868 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 869 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 3264 of file manager.c.

Referenced by __manager_event().

#define MAX_BLACKLIST_CMD_LEN   2

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

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

Definition at line 143 of file manager.c.

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

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

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

Definition at line 1004 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().

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

Definition at line 224 of file manager.c.

Referenced by action_waitevent(), and process_events().


Enumeration Type Documentation

enum error_type

Doxygen group

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

Definition at line 78 of file manager.c.


Function Documentation

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

Definition at line 870 of file manager.c.

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

Referenced by astman_get_header(), and process_message().

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

static void __fini_actions ( void   )  [static]

Definition at line 250 of file manager.c.

00257 {

static void __fini_manager_hooks ( void   )  [static]

Definition at line 253 of file manager.c.

00257 {

static void __fini_users ( void   )  [static]

Definition at line 247 of file manager.c.

00257 {

static void __init_actions ( void   )  [static]

Definition at line 250 of file manager.c.

00257 {

static void __init_astman_append_buf ( void   )  [static]

thread local buffer for astman_append

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

Definition at line 960 of file manager.c.

00970 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 3263 of file manager.c.

03266 : Send AMI event to client */

static void __init_manager_hooks ( void   )  [static]

Definition at line 253 of file manager.c.

00257 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 961 of file manager.c.

00970 {

static void __init_users ( void   )  [static]

Definition at line 247 of file manager.c.

00257 {

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 3267 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_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, eventqent::seq, ast_str::str, and mansession_session::waiting_thread.

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

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

Definition at line 2143 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1737 of file manager.c.

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

Referenced by __init_manager().

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

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

Manager command "command" - execute CLI command.

Definition at line 2233 of file manager.c.

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

Referenced by __init_manager().

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

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

Show PBX core settings information.

Definition at line 2683 of file manager.c.

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

Referenced by __init_manager().

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

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

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

Referenced by __init_manager().

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

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

Show PBX core status information.

Definition at line 2729 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1548 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1697 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2565 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1152 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1246 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1822 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1759 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1196 of file manager.c.

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

Referenced by __init_manager().

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

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

Note:
The actionlock is read-locked by the caller of this function

Definition at line 1673 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1722 of file manager.c.

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

Referenced by __init_manager().

01723 {
01724    if (authenticate(s, m)) {
01725       sleep(1);
01726       astman_send_error(s, m, "Authentication failed");
01727       return -1;
01728    }
01729    s->session->authenticated = 1;
01730    if (manager_displayconnects(s->session))
01731       ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
01732    ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
01733    astman_send_ack(s, m, "Authentication accepted");
01734    return 0;
01735 }

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

Definition at line 1716 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

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

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

Definition at line 2533 of file manager.c.

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

Referenced by __init_manager().

02534 {
02535    const char *mailbox = astman_get_header(m, "Mailbox");
02536    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
02537 
02538    if (ast_strlen_zero(mailbox)) {
02539       astman_send_error(s, m, "Mailbox not specified");
02540       return 0;
02541    }
02542    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
02543    astman_start_ack(s, m);
02544    astman_append(s,   "Message: Mailbox Message Count\r\n"
02545             "Mailbox: %s\r\n"
02546             "UrgMessages: %d\r\n"
02547             "NewMessages: %d\r\n"
02548             "OldMessages: %d\r\n"
02549             "\r\n",
02550             mailbox, urgentmsgs, newmsgs, oldmsgs);
02551    return 0;
02552 }

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

Definition at line 2504 of file manager.c.

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

Referenced by __init_manager().

02505 {
02506    const char *mailbox = astman_get_header(m, "Mailbox");
02507    int ret;
02508 
02509    if (ast_strlen_zero(mailbox)) {
02510       astman_send_error(s, m, "Mailbox not specified");
02511       return 0;
02512    }
02513    ret = ast_app_has_voicemail(mailbox, NULL);
02514    astman_start_ack(s, m);
02515    astman_append(s, "Message: Mailbox Status\r\n"
02516           "Mailbox: %s\r\n"
02517           "Waiting: %d\r\n\r\n", mailbox, ret);
02518    return 0;
02519 }

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

Definition at line 2367 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1137 of file manager.c.

References astman_append().

Referenced by __init_manager().

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

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

action_redirect: The redirect manager command

Definition at line 2059 of file manager.c.

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

Referenced by __init_manager().

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

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

Send a reload event.

Definition at line 2768 of file manager.c.

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

Referenced by __init_manager().

02769 {
02770    const char *module = astman_get_header(m, "Module");
02771    int res = ast_module_reload(S_OR(module, NULL));
02772 
02773    if (res == 2)
02774       astman_send_ack(s, m, "Module Reloaded");
02775    else
02776       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
02777    return 0;
02778 }

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

Definition at line 2014 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1785 of file manager.c.

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

Referenced by __init_manager().

01786 {
01787    struct ast_channel *c = NULL;
01788    const char *name = astman_get_header(m, "Channel");
01789    const char *varname = astman_get_header(m, "Variable");
01790    const char *varval = astman_get_header(m, "Value");
01791 
01792    if (ast_strlen_zero(varname)) {
01793       astman_send_error(s, m, "No variable specified");
01794       return 0;
01795    }
01796 
01797    if (!ast_strlen_zero(name)) {
01798       c = ast_get_channel_by_name_locked(name);
01799       if (!c) {
01800          astman_send_error(s, m, "No such channel");
01801          return 0;
01802       }
01803    }
01804 
01805    pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
01806 
01807    if (c)
01808       ast_channel_unlock(c);
01809 
01810    astman_send_ack(s, m, "Variable Set");
01811 
01812    return 0;
01813 }

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

Manager "status" command to show channels.

Definition at line 1879 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2596 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 1467 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2659 of file manager.c.

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

Referenced by __init_manager().

02660 {
02661    const char *event = astman_get_header(m, "UserEvent");
02662    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
02663    int x;
02664 
02665    ast_str_reset(body);
02666 
02667    for (x = 0; x < m->hdrcount; x++) {
02668       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
02669          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
02670       }
02671    }
02672 
02673    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, body->str);
02674    return 0;
02675 }

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

Definition at line 1573 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 3240 of file manager.c.

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

Referenced by __init_manager(), and __manager_event().

03241 {
03242    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
03243    static int seq;   /* sequence number */
03244 
03245    if (!tmp)
03246       return -1;
03247 
03248    /* need to init all fields, because ast_malloc() does not */
03249    tmp->usecount = 0;
03250    tmp->category = category;
03251    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
03252    AST_LIST_NEXT(tmp, eq_next) = NULL;
03253    strcpy(tmp->eventdata, str);
03254 
03255    AST_LIST_LOCK(&all_events);
03256    AST_LIST_INSERT_TAIL(&all_events, tmp, eq_next);
03257    AST_LIST_UNLOCK(&all_events);
03258 
03259    return 0;
03260 }

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

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

feel free to move this to app.c -anthm

Definition at line 413 of file manager.c.

References eventqent::next.

Referenced by get_perm().

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

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

register a new command with manager, including online help. This is the preferred way to register a manager command

Register a manager command with the manager interface.

Definition at line 3411 of file manager.c.

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

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

03412 {
03413    struct manager_action *cur = NULL;
03414 
03415    if (!(cur = ast_calloc(1, sizeof(*cur))))
03416       return -1;
03417 
03418    cur->action = action;
03419    cur->authority = auth;
03420    cur->func = func;
03421    cur->synopsis = synopsis;
03422    cur->description = description;
03423 
03424    if (ast_manager_register_struct(cur)) {
03425       ast_free(cur);
03426       return -1;
03427    }
03428 
03429    return 0;
03430 }

void ast_manager_register_hook ( struct manager_custom_hook hook  ) 

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

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

Parameters:
hook struct manager_custom_hook object to add

Definition at line 256 of file manager.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

static int ast_manager_register_struct ( struct manager_action act  )  [static]

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

03376 {
03377    struct manager_action *cur, *prev = NULL;
03378    struct timespec tv = { 5, };
03379 
03380    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03381       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03382       return -1;
03383    }
03384    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03385       int ret = strcasecmp(cur->action, act->action);
03386       if (ret == 0) {
03387          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
03388          AST_RWLIST_UNLOCK(&actions);
03389          return -1;
03390       }
03391       if (ret > 0) { /* Insert these alphabetically */
03392          prev = cur;
03393          break;
03394       }
03395    }
03396 
03397    if (prev)
03398       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
03399    else
03400       AST_RWLIST_INSERT_HEAD(&actions, act, list);
03401 
03402    ast_verb(2, "Manager registered action %s\n", act->action);
03403 
03404    AST_RWLIST_UNLOCK(&actions);
03405 
03406    return 0;
03407 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

03343 {
03344    struct manager_action *cur;
03345    struct timespec tv = { 5, };
03346 
03347    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
03348       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
03349       return -1;
03350    }
03351    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
03352       if (!strcasecmp(action, cur->action)) {
03353          AST_RWLIST_REMOVE_CURRENT(list);
03354          ast_free(cur);
03355          ast_verb(2, "Manager unregistered action %s\n", action);
03356          break;
03357       }
03358    }
03359    AST_RWLIST_TRAVERSE_SAFE_END;
03360    AST_RWLIST_UNLOCK(&actions);
03361 
03362    return 0;
03363 }

void ast_manager_unregister_hook ( struct manager_custom_hook hook  ) 

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

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

Parameters:
hook struct manager_custom_hook object to delete

Definition at line 265 of file manager.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

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

utility functions for creating AMI replies

Definition at line 969 of file manager.c.

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

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

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

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

Get header from mananger transaction.

Definition at line 897 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

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

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

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

Get a linked list of the Variable: headers.

Definition at line 903 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

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

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

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

Send error in manager transaction.

Definition at line 1027 of file manager.c.

References astman_send_response_full().

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

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

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

Send ack in manager list transaction.

Definition at line 1042 of file manager.c.

References astman_send_response_full().

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

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

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

Send response in manager transaction.

Definition at line 1022 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

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

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

Definition at line 1005 of file manager.c.

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

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

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

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

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

Definition at line 1071 of file manager.c.

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

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

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

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

Convert authority code to a list of options.

Definition at line 389 of file manager.c.

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

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

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

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

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

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

int check_manager_enabled ( void   ) 

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

Check if AMI is enabled.

Definition at line 316 of file manager.c.

Referenced by handle_show_settings().

00317 {
00318    return manager_enabled;
00319 }

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

Definition at line 472 of file manager.c.

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

Referenced by process_message().

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

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 321 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

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

static void destroy_session ( struct mansession_session session  )  [static]

static int do_message ( struct mansession s  )  [static]

Definition at line 3104 of file manager.c.

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

Referenced by session_do().

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

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

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

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

static void free_session ( struct mansession_session session  )  [static]

Definition at line 834 of file manager.c.

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

Referenced by destroy_session(), and purge_sessions().

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

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

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

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

Definition at line 3034 of file manager.c.

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

Referenced by do_message(), and skinny_session().

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

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

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

Definition at line 491 of file manager.c.

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

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

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

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

Definition at line 430 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

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

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

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

Definition at line 330 of file manager.c.

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

Referenced by generic_http_callback(), and session_do().

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

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

CLI command manager reload.

Definition at line 784 of file manager.c.

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

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

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

Definition at line 565 of file manager.c.

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

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

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

Definition at line 588 of file manager.c.

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

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

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

Definition at line 651 of file manager.c.

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

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

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

Definition at line 518 of file manager.c.

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

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

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

CLI command manager list commands.

Definition at line 695 of file manager.c.

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

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

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

CLI command manager list connected.

Definition at line 723 of file manager.c.

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

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

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

CLI command manager list eventq.

Definition at line 758 of file manager.c.

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

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

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

Definition at line 1310 of file manager.c.

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

Referenced by action_updateconfig().

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

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

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

Definition at line 1229 of file manager.c.

Referenced by action_getconfigjson().

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

static int manager_displayconnects ( struct mansession_session session  )  [static]

Get displayconnects config option.

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

Definition at line 505 of file manager.c.

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

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

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

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

Definition at line 2858 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 2911 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 3365 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

03366 {
03367    /* Notify managers of change */
03368    char hint[512];
03369    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
03370 
03371    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
03372    return 0;
03373 }

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

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

Referenced by do_message(), and process_message().

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

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

Definition at line 2965 of file manager.c.

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

Referenced by do_message(), generic_http_callback(), and http_post_callback().

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

static void purge_events ( void   )  [static]

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

Definition at line 349 of file manager.c.

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

Referenced by purge_old_stuff().

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

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

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

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

static void ref_event ( struct eventqent e  )  [static]

Definition at line 826 of file manager.c.

References ast_atomic_fetchadd_int(), and eventqent::usecount.

Referenced by action_waitevent(), and process_events().

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

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

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

Definition at line 944 of file manager.c.

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

Referenced by astman_append(), and process_events().

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

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

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

Definition at line 3136 of file manager.c.

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

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

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

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

Definition at line 1052 of file manager.c.

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

Referenced by action_events(), and authenticate().

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

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

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

Definition at line 449 of file manager.c.

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

Referenced by set_eventmask().

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

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

Definition at line 820 of file manager.c.

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

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

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


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 123 of file manager.c.

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

Definition at line 960 of file manager.c.

Referenced by astman_append().

int block_sockets [static]

Definition at line 129 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 803 of file manager.c.

Referenced by __init_manager().

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

Referenced by check_blacklist().

int displayconnects = 1 [static]

Definition at line 122 of file manager.c.

int httptimeout = 60 [static]

Definition at line 125 of file manager.c.

int manager_debug [static]

enable some debugging code in the manager

Definition at line 132 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 126 of file manager.c.

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

Definition at line 3263 of file manager.c.

Referenced by __manager_event().

char mandescr_atxfer[] [static]

Definition at line 2134 of file manager.c.

Referenced by __init_manager().

char mandescr_command[] [static]

Initial value:

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

Definition at line 2226 of file manager.c.

Referenced by __init_manager().

char mandescr_coresettings[] [static]

Initial value:

"Description: Query for Core PBX settings.\n"
"Variables: (Names marked with * are optional)\n"
"       *ActionID: ActionID of this transaction\n"

Definition at line 2677 of file manager.c.

Referenced by __init_manager().

char mandescr_coreshowchannels[] [static]

Initial value:

"Description: List currently defined channels and some information\n"
"             about them.\n"
"Variables:\n"
"          ActionID: Optional Action id for message matching.\n"

Definition at line 2780 of file manager.c.

Referenced by __init_manager().

char mandescr_corestatus[] [static]

Initial value:

"Description: Query for Core PBX status.\n"
"Variables: (Names marked with * are optional)\n"
"       *ActionID: ActionID of this transaction\n"

Definition at line 2723 of file manager.c.

Referenced by __init_manager().

char mandescr_createconfig[] [static]

Definition at line 1541 of file manager.c.

Referenced by __init_manager().

char mandescr_events[] [static]

Definition at line 1689 of file manager.c.

Referenced by __init_manager().

char mandescr_extensionstate[] [static]

Definition at line 2554 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfig[] [static]

Definition at line 1145 of file manager.c.

Referenced by __init_manager().

char mandescr_getconfigjson[] [static]

Definition at line 1239 of file manager.c.

Referenced by __init_manager().

char mandescr_getvar[] [static]

Definition at line 1815 of file manager.c.

Referenced by __init_manager().

char mandescr_hangup[] [static]

Initial value:

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

Definition at line 1754 of file manager.c.

Referenced by __init_manager().

char mandescr_listcategories[] [static]

Initial value:

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

Definition at line 1190 of file manager.c.

Referenced by __init_manager().

char mandescr_listcommands[] [static]

Initial value:

"Description: Returns the action name and synopsis for every\n"
"  action that is available to the user\n"
"Variables: NONE\n"

Definition at line 1667 of file manager.c.

Referenced by __init_manager().

char mandescr_logoff[] [static]

Initial value:

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

Definition at line 1712 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxcount[] [static]

Definition at line 2521 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 2493 of file manager.c.

Referenced by __init_manager().

char mandescr_modulecheck[] [static]

Definition at line 2848 of file manager.c.

Referenced by __init_manager().

char mandescr_moduleload[] [static]

Definition at line 2900 of file manager.c.

Referenced by __init_manager().

char mandescr_originate[] [static]

Definition at line 2351 of file manager.c.

Referenced by __init_manager().

char mandescr_ping[] [static]

Initial value:

"Description: A 'Ping' action will ellicit a 'Pong' response.  Used to keep the\n"
"  manager connection open.\n"
"Variables: NONE\n"
Manager PING.

Definition at line 1132 of file manager.c.

Referenced by __init_manager().

char mandescr_redirect[] [static]

Definition at line 2048 of file manager.c.

Referenced by __init_manager().

char mandescr_reload[] [static]

Initial value:

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

Definition at line 2761 of file manager.c.

Referenced by __init_manager().

char mandescr_sendtext[] [static]

Definition at line 2007 of file manager.c.

Referenced by __init_manager().

char mandescr_setvar[] [static]

Definition at line 1778 of file manager.c.

Referenced by __init_manager().

char mandescr_status[] [static]

Definition at line 1867 of file manager.c.

Referenced by __init_manager().

char mandescr_timeout[] [static]

Definition at line 2589 of file manager.c.

Referenced by __init_manager().

char mandescr_updateconfig[] [static]

Definition at line 1453 of file manager.c.

Referenced by __init_manager().

char mandescr_userevent[] [static]

Definition at line 2652 of file manager.c.

Referenced by __init_manager().

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1566 of file manager.c.

Referenced by __init_manager().

int num_sessions [static]

Definition at line 130 of file manager.c.

struct permalias perms[] [static]

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

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

int timestampevents [static]

Definition at line 124 of file manager.c.

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

Definition at line 961 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 127 of file manager.c.

char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 145 of file manager.c.


Generated on Wed Oct 28 11:53:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6