Wed Mar 3 23:09:49 2010

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  mansession
struct  mansession_session
struct  permalias

Defines

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

callback to display queues status in manager

callback to display list of locally configured nodes


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 964 of file manager.c.

Referenced by astman_append().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 867 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 868 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 869 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 3262 of file manager.c.

Referenced by __manager_event().

#define MAX_BLACKLIST_CMD_LEN   2

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

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

Definition at line 143 of file manager.c.

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

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

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

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

Definition at line 1004 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().

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

Definition at line 224 of file manager.c.

Referenced by action_waitevent(), and process_events().


Enumeration Type Documentation

enum error_type

Doxygen group

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

Definition at line 78 of file manager.c.


Function Documentation

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

Definition at line 870 of file manager.c.

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

Referenced by astman_get_header(), and process_message().

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

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

manager_event: Send AMI event to client

Definition at line 3265 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_INITSIZE, mansession_session::pending_event, eventqent::seq, ast_str::str, and mansession_session::waiting_thread.

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

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 = mkstemp(template);
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    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
02253    if (!ast_strlen_zero(id))
02254       astman_append(s, "ActionID: %s\r\n", id);
02255    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
02256    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
02257    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
02258 
02259    /* This has a potential to overflow the stack.  Hence, use the heap. */
02260    buf = ast_calloc(1, l + 1);
02261    final_buf = ast_calloc(1, l + 1);
02262    if (buf) {
02263       lseek(fd, 0, SEEK_SET);
02264       if (read(fd, buf, l) < 0) {
02265          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
02266       }
02267       buf[l] = '\0';
02268       if (final_buf) {
02269          term_strip(final_buf, buf, l);
02270          final_buf[l] = '\0';
02271       }
02272       astman_append(s, "%s", S_OR(final_buf, buf));
02273       ast_free(buf);
02274    }
02275    close(fd);
02276    unlink(template);
02277    astman_append(s, "--END COMMAND--\r\n\r\n");
02278    if (final_buf)
02279       ast_free(final_buf);
02280    return 0;
02281 }

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

Show PBX core settings information.

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

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

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

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

Referenced by __init_manager().

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

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

Show PBX core status information.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by __init_manager().

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

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_APP_ARG, ast_channel_unlock, ast_channel_walk_locked(), AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), ast_get_channel_by_name_locked(), AST_STANDARD_APP_ARGS, ast_state2str(), ast_str_append(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::cdr, channels, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, name, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_OR, ast_cdr::start, ast_str::str, and str.

Referenced by __init_manager().

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

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

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 2657 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, and ast_str::str.

Referenced by __init_manager().

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

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

Definition at line 1573 of file manager.c.

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

Referenced by __init_manager().

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

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

Definition at line 3238 of file manager.c.

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

Referenced by __init_manager(), and __manager_event().

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

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

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

feel free to move this to app.c -anthm

Definition at line 413 of file manager.c.

Referenced by get_perm().

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

static AST_LIST_HEAD_STATIC ( sessions  ,
mansession_session   
) [static]
static AST_LIST_HEAD_STATIC ( all_events  ,
eventqent   
) [static]
int ast_manager_register2 ( const char *  action,
int  auth,
int(*)(struct mansession *s, const struct message *m)  func,
const char *  synopsis,
const char *  description 
)

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

Register a manager command with the manager interface.

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

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

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

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

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

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

void ast_manager_unregister_hook ( struct manager_custom_hook hook  ) 

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

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

Parameters:
hook struct manager_custom_hook object to delete

Definition at line 265 of file manager.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

static AST_RWLIST_HEAD_STATIC ( manager_hooks  ,
manager_custom_hook   
) [static]

list of hooks registered

static AST_RWLIST_HEAD_STATIC ( actions  ,
manager_action   
) [static]

list of actions registered

static AST_RWLIST_HEAD_STATIC ( users  ,
ast_manager_user   
) [static]

list of users found in the config file

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

thread local buffer for astman_append

Note:
This can not be defined within the astman_append() function because it declares a couple of functions that get used to initialize the thread local storage key.
void astman_append ( struct mansession s,
const char *  fmt,
  ... 
)

utility functions for creating AMI replies

Definition at line 969 of file manager.c.

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

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

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

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

Get header from mananger transaction.

Definition at line 897 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

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

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

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

Get a linked list of the Variable: headers.

Definition at line 903 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

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

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

Send error in manager transaction.

Definition at line 1027 of file manager.c.

References astman_send_response_full().

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

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

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

Send ack in manager list transaction.

Definition at line 1042 of file manager.c.

References astman_send_response_full().

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

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

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

Send response in manager transaction.

Definition at line 1022 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

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

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

Definition at line 1005 of file manager.c.

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

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

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

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

Definition at line 1071 of file manager.c.

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

Referenced by action_login().

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

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

Convert authority code to a list of options.

Definition at line 389 of file manager.c.

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

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

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

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

Definition at line 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, and mansession_session::username.

Referenced by process_message().

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

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 321 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

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

static void destroy_session ( struct mansession_session session  )  [static]

Definition at line 852 of file manager.c.

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

Referenced by generic_http_callback(), and session_do().

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

static int do_message ( struct mansession s  )  [static]

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

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

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

Definition at line 2302 of file manager.c.

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

Referenced by action_originate().

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

static void free_session ( struct mansession_session session  )  [static]

Definition at line 834 of file manager.c.

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

Referenced by destroy_session(), and purge_sessions().

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

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

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

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

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

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

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

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

Definition at line 491 of file manager.c.

References AST_RWLIST_TRAVERSE, and ast_manager_user::username.

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

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

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

Definition at line 430 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

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

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

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

Definition at line 330 of file manager.c.

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

Referenced by generic_http_callback(), and session_do().

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

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

CLI command manager reload.

Definition at line 784 of file manager.c.

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

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

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

Definition at line 565 of file manager.c.

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

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

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

Definition at line 588 of file manager.c.

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

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

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

Definition at line 651 of file manager.c.

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

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

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

Definition at line 518 of file manager.c.

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

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

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

CLI command manager list commands.

Definition at line 695 of file manager.c.

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

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

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

CLI command manager list connected.

Definition at line 723 of file manager.c.

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

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

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

CLI command manager list eventq.

Definition at line 758 of file manager.c.

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

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

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

Definition at line 1310 of file manager.c.

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

Referenced by action_updateconfig().

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

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

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

Definition at line 1229 of file manager.c.

Referenced by action_getconfigjson().

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

static int manager_displayconnects ( struct mansession_session session  )  [static]

Get displayconnects config option.

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

Definition at line 505 of file manager.c.

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

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

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

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

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

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

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

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

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

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

Definition at line 3363 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

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

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

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

Referenced by do_message(), and process_message().

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

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

Definition at line 2963 of file manager.c.

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

Referenced by do_message(), and generic_http_callback().

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

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

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

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

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

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

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

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

Definition at line 1052 of file manager.c.

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

Referenced by action_events(), and authenticate().

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

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

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

Definition at line 449 of file manager.c.

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

Referenced by set_eventmask().

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

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

Definition at line 820 of file manager.c.

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

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

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


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 123 of file manager.c.

int block_sockets [static]

Definition at line 129 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 803 of file manager.c.

Referenced by __init_manager().

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

Referenced by check_blacklist().

int displayconnects = 1 [static]

Definition at line 122 of file manager.c.

int httptimeout = 60 [static]

Definition at line 125 of file manager.c.

int manager_debug [static]

enable some debugging code in the manager

Definition at line 132 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 126 of file manager.c.

char mandescr_atxfer[] [static]

Definition at line 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 2675 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 2778 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 2721 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 2552 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 2519 of file manager.c.

Referenced by __init_manager().

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 2491 of file manager.c.

Referenced by __init_manager().

char mandescr_modulecheck[] [static]

Definition at line 2846 of file manager.c.

Referenced by __init_manager().

char mandescr_moduleload[] [static]

Definition at line 2898 of file manager.c.

Referenced by __init_manager().

char mandescr_originate[] [static]

Definition at line 2349 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 2759 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 2587 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 2650 of file manager.c.

Referenced by __init_manager().

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1566 of file manager.c.

Referenced by __init_manager().

int num_sessions [static]

Definition at line 130 of file manager.c.

struct permalias perms[] [static]

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

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

int timestampevents [static]

Definition at line 124 of file manager.c.

int webmanager_enabled = 0 [static]

Definition at line 127 of file manager.c.

char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 145 of file manager.c.


Generated on 3 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1