Sat Apr 12 07:12:56 2008

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

struct  ast_manager_user
struct  eventqent
struct  fast_originate_helper
struct  mansession
struct  permalias
struct  variable_count

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
#define MANAGER_EVENT_BUF_INITSIZE   256

Functions

static void * accept_thread (void *ignore)
static int action_command (struct mansession *s, const struct message *m)
 action_command: Manager command "command" - execute CLI command
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_getvar (struct mansession *s, const struct message *m)
static int action_hangup (struct mansession *s, const struct message *m)
static int action_listcommands (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_message (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_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 struct ast_manager_userast_get_manager_by_name_locked (const char *name)
static int ast_instring (const char *bigstr, const char *smallstr, char delim)
static int ast_is_number (const char *string)
static AST_LIST_HEAD_STATIC (users, ast_manager_user)
static AST_LIST_HEAD_STATIC (sessions, mansession)
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
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 AST_RWLOCK_DEFINE_STATIC (actionlock)
 AST_THREADSTORAGE (astman_append_buf, astman_append_buf_init)
 AST_THREADSTORAGE (manager_event_buf, manager_event_buf_init)
void astman_append (struct mansession *s, const char *fmt,...)
const char * astman_get_header (const struct message *m, char *var)
struct ast_variableastman_get_variables (const struct message *m)
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)
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
static int authenticate (struct mansession *s, const struct message *m)
static char * authority_to_str (int authority, char *res, int reslen)
 Convert authority code to string with serveral options.
static char * complete_show_mancmd (const char *line, const char *word, int pos, int state)
static int compress_char (char c)
static void destroy_session (struct mansession *s)
static int do_message (struct mansession *s)
static void * fast_originate (void *data)
static void free_session (struct mansession *s)
static int get_input (struct mansession *s, char *output)
static int get_perm (const char *instr)
static int handle_showmanager (int fd, int argc, char *argv[])
static int handle_showmanagers (int fd, int argc, char *argv[])
static int handle_showmancmd (int fd, int argc, char *argv[])
static int handle_showmancmds (int fd, int argc, char *argv[])
 CLI command Should change to "manager show commands".
static int handle_showmanconn (int fd, int argc, char *argv[])
 CLI command show manager connected.
static int handle_showmaneventq (int fd, int argc, char *argv[])
 CLI command show manager connected.
static void handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg)
static char * html_translate (char *in)
int manager_event (int category, const char *event, const char *fmt,...)
 manager_event: Send AMI event to client
static int manager_state_cb (char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
static void * session_do (void *data)
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 void unuse_eventqent (struct eventqent *e)
static int variable_count_cmp_fn (void *obj, void *vstr, int flags)
static int variable_count_hash_fn (const void *vvc, const int flags)
static void xml_copy_escape (char **dst, size_t *maxlen, const char *src, int lower)
static char * xml_translate (char *in, struct ast_variable *vars)

Variables

static int asock = -1
static int block_sockets
static struct ast_cli_entry cli_manager []
static struct ast_cli_entry cli_show_manager_command_deprecated
static struct ast_cli_entry cli_show_manager_commands_deprecated
static struct ast_cli_entry cli_show_manager_connected_deprecated
static struct ast_cli_entry cli_show_manager_eventq_deprecated
static const char * command_blacklist []
static int displayconnects = 1
static int enabled
static struct manager_actionfirst_action
static int httptimeout = 60
static char mandescr_command []
static char mandescr_events []
static char mandescr_extensionstate []
static char mandescr_getconfig []
static char mandescr_getvar []
static char mandescr_hangup []
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_message []
static char mandescr_originate []
static char mandescr_ping []
 Manager PING.
static char mandescr_redirect []
static char mandescr_setvar []
static char mandescr_timeout []
static char mandescr_updateconfig []
static char mandescr_userevent []
static char mandescr_waitevent []
 Manager WAITEVENT.
struct eventqentmaster_eventq = NULL
static int num_sessions
static struct permalias perms []
static int portno = DEFAULT_MANAGER_PORT
static char showmanager_help []
static char showmanagers_help []
static char showmancmd_help []
static char showmancmds_help []
static char showmanconn_help []
static char showmaneventq_help []
static pthread_t t
static int timestampevents

Detailed Description

callback to display queues status in manager


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

Definition at line 120 of file manager.c.

Referenced by astman_append().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 117 of file manager.c.

Referenced by manager_event().


Function Documentation

static void* accept_thread ( void *  ignore  )  [static]

Definition at line 2392 of file manager.c.

References mansession::__lock, ast_calloc, ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_verbose(), mansession::authenticated, destroy_session(), errno, mansession::eventq, pollfd::events, mansession::fd, pollfd::fd, ast_channel::flags, free, free_session(), mansession::inuse, LOG_NOTICE, LOG_WARNING, eventqent::next, option_verbose, poll(), POLLIN, s, mansession::send_events, session_do(), mansession::sessiontimeout, mansession::sin, mansession::t, eventqent::usecount, mansession::username, VERBOSE_PREFIX_2, mansession::waiting_thread, and mansession::writetimeout.

Referenced by init_manager(), and reload_config().

02393 {
02394    int as;
02395    struct sockaddr_in sin;
02396    socklen_t sinlen;
02397    struct eventqent *eqe;
02398    struct mansession *s;
02399    struct protoent *p;
02400    int arg = 1;
02401    int flags;
02402    pthread_attr_t attr;
02403    time_t now;
02404    struct pollfd pfds[1];
02405 
02406    pthread_attr_init(&attr);
02407    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02408 
02409    for (;;) {
02410       time(&now);
02411       AST_LIST_LOCK(&sessions);
02412       AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
02413          if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
02414             AST_LIST_REMOVE_CURRENT(&sessions, list);
02415             num_sessions--;
02416             if (s->authenticated && (option_verbose > 1) && displayconnects) {
02417                ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' timed out from %s\n",
02418                   s->username, ast_inet_ntoa(s->sin.sin_addr));
02419             }
02420             free_session(s);
02421             break;   
02422          }
02423       }
02424       AST_LIST_TRAVERSE_SAFE_END
02425       /* Purge master event queue of old, unused events, but make sure we
02426          always keep at least one in the queue */
02427       eqe = master_eventq;
02428       while (master_eventq->next && !master_eventq->usecount) {
02429          eqe = master_eventq;
02430          master_eventq = master_eventq->next;
02431          free(eqe);
02432       }
02433       AST_LIST_UNLOCK(&sessions);
02434 
02435       sinlen = sizeof(sin);
02436       pfds[0].fd = asock;
02437       pfds[0].events = POLLIN;
02438       /* Wait for something to happen, but timeout every few seconds so
02439          we can ditch any old manager sessions */
02440       if (poll(pfds, 1, 5000) < 1)
02441          continue;
02442       as = accept(asock, (struct sockaddr *)&sin, &sinlen);
02443       if (as < 0) {
02444          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
02445          continue;
02446       }
02447       p = getprotobyname("tcp");
02448       if (p) {
02449          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
02450             ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
02451          }
02452       }
02453       if (!(s = ast_calloc(1, sizeof(*s))))
02454          continue;
02455 
02456       memcpy(&s->sin, &sin, sizeof(sin));
02457       s->writetimeout = 100;
02458       s->waiting_thread = AST_PTHREADT_NULL;
02459 
02460       if (!block_sockets) {
02461          /* For safety, make sure socket is non-blocking */
02462          flags = fcntl(as, F_GETFL);
02463          fcntl(as, F_SETFL, flags | O_NONBLOCK);
02464       } else {
02465          flags = fcntl(as, F_GETFL);
02466          fcntl(as, F_SETFL, flags & ~O_NONBLOCK);
02467       }
02468       ast_mutex_init(&s->__lock);
02469       s->fd = as;
02470       s->send_events = -1;
02471       AST_LIST_LOCK(&sessions);
02472       AST_LIST_INSERT_HEAD(&sessions, s, list);
02473       num_sessions++;
02474       /* Find the last place in the master event queue and hook ourselves
02475          in there */
02476       s->eventq = master_eventq;
02477       while(s->eventq->next)
02478          s->eventq = s->eventq->next;
02479       ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
02480       AST_LIST_UNLOCK(&sessions);
02481       if (ast_pthread_create_background(&s->t, &attr, session_do, s))
02482          destroy_session(s);
02483    }
02484    pthread_attr_destroy(&attr);
02485    return NULL;
02486 }

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

action_command: Manager command "command" - execute CLI command

Definition at line 1758 of file manager.c.

References ast_calloc, ast_cli_command(), ast_free, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), mansession::fd, S_OR, and term_strip().

Referenced by init_manager().

01759 {
01760    const char *cmd = astman_get_header(m, "Command");
01761    const char *id = astman_get_header(m, "ActionID");
01762    char *buf, *final_buf;
01763    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
01764    int fd = mkstemp(template), i = 0;
01765    off_t l;
01766 
01767    for (i = 0; i < sizeof(command_blacklist) / sizeof(command_blacklist[0]); i++) {
01768       if (!strncmp(cmd, command_blacklist[i], strlen(command_blacklist[i]))) {
01769          astman_send_error(s, m, "Command blacklisted");
01770          return 0;
01771       }
01772    }
01773 
01774    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
01775    if (!ast_strlen_zero(id))
01776       astman_append(s, "ActionID: %s\r\n", id);
01777    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
01778    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
01779    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
01780 
01781    /* This has a potential to overflow the stack.  Hence, use the heap. */
01782    buf = ast_calloc(1, l + 1);
01783    final_buf = ast_calloc(1, l + 1);
01784    if (buf) {
01785       lseek(fd, 0, SEEK_SET);
01786       read(fd, buf, l);
01787       buf[l] = '\0';
01788       if (final_buf) {
01789          term_strip(final_buf, buf, l);
01790          final_buf[l] = '\0';
01791       }
01792       astman_append(s, "%s", S_OR(final_buf, buf));
01793       ast_free(buf);
01794    }
01795    close(fd);
01796    unlink(template);
01797    astman_append(s, "--END COMMAND--\r\n\r\n");
01798    if (final_buf)
01799       ast_free(final_buf);
01800    return 0;
01801 }

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

Definition at line 1387 of file manager.c.

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

Referenced by init_manager().

01388 {
01389    const char *mask = astman_get_header(m, "EventMask");
01390    int res;
01391 
01392    res = set_eventmask(s, mask);
01393    if (res > 0)
01394       astman_send_response(s, m, "Events On", NULL);
01395    else if (res == 0)
01396       astman_send_response(s, m, "Events Off", NULL);
01397 
01398    return 0;
01399 }

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

Definition at line 2073 of file manager.c.

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

Referenced by init_manager().

02074 {
02075    const char *exten = astman_get_header(m, "Exten");
02076    const char *context = astman_get_header(m, "Context");
02077    const char *id = astman_get_header(m,"ActionID");
02078    char idText[256] = "";
02079    char hint[256] = "";
02080    int status;
02081    if (ast_strlen_zero(exten)) {
02082       astman_send_error(s, m, "Extension not specified");
02083       return 0;
02084    }
02085    if (ast_strlen_zero(context))
02086       context = "default";
02087    status = ast_extension_state(NULL, context, exten);
02088    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
02089         if (!ast_strlen_zero(id)) {
02090                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02091         }
02092    astman_append(s, "Response: Success\r\n"
02093                     "%s"
02094                "Message: Extension Status\r\n"
02095                "Exten: %s\r\n"
02096                "Context: %s\r\n"
02097                "Hint: %s\r\n"
02098                "Status: %d\r\n\r\n",
02099                idText,exten, context, hint, status);
02100    return 0;
02101 }

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

Definition at line 1116 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load_with_comments(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), lineno, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by init_manager().

01117 {
01118    struct ast_config *cfg;
01119    const char *fn = astman_get_header(m, "Filename");
01120    int catcount = 0;
01121    int lineno = 0;
01122    char *category=NULL;
01123    struct ast_variable *v;
01124    char idText[256] = "";
01125    const char *id = astman_get_header(m, "ActionID");
01126 
01127    if (!ast_strlen_zero(id))
01128       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01129 
01130    if (ast_strlen_zero(fn)) {
01131       astman_send_error(s, m, "Filename not specified");
01132       return 0;
01133    }
01134    if (!(cfg = ast_config_load_with_comments(fn))) {
01135       astman_send_error(s, m, "Config file not found");
01136       return 0;
01137    }
01138    astman_append(s, "Response: Success\r\n%s", idText);
01139    while ((category = ast_category_browse(cfg, category))) {
01140       lineno = 0;
01141       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
01142       for (v = ast_variable_browse(cfg, category); v; v = v->next)
01143          astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
01144       catcount++;
01145    }
01146    ast_config_destroy(cfg);
01147    astman_append(s, "\r\n");
01148 
01149    return 0;
01150 }

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

Definition at line 1531 of file manager.c.

References ast_channel_unlock, ast_func_read(), ast_get_channel_by_name_locked(), ast_strdupa, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), copy(), name, and pbx_retrieve_variable().

Referenced by init_manager().

01532 {
01533    struct ast_channel *c = NULL;
01534    const char *name = astman_get_header(m, "Channel");
01535    const char *varname = astman_get_header(m, "Variable");
01536    const char *id = astman_get_header(m,"ActionID");
01537    char *varval;
01538    char workspace[1024] = "";
01539 
01540    if (ast_strlen_zero(varname)) {
01541       astman_send_error(s, m, "No variable specified");
01542       return 0;
01543    }
01544 
01545    if (!ast_strlen_zero(name)) {
01546       c = ast_get_channel_by_name_locked(name);
01547       if (!c) {
01548          astman_send_error(s, m, "No such channel");
01549          return 0;
01550       }
01551    }
01552 
01553    if (varname[strlen(varname) - 1] == ')') {
01554       char *copy = ast_strdupa(varname);
01555 
01556       ast_func_read(c, copy, workspace, sizeof(workspace));
01557       varval = workspace;
01558    } else {
01559       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
01560    }
01561 
01562    if (c)
01563       ast_channel_unlock(c);
01564    astman_append(s, "Response: Success\r\n"
01565       "Variable: %s\r\nValue: %s\r\n", varname, varval);
01566    if (!ast_strlen_zero(id))
01567       astman_append(s, "ActionID: %s\r\n",id);
01568    astman_append(s, "\r\n");
01569 
01570    return 0;
01571 }

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

Definition at line 1416 of file manager.c.

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

Referenced by init_manager().

01417 {
01418    struct ast_channel *c = NULL;
01419    const char *name = astman_get_header(m, "Channel");
01420    const char *uniqueid = astman_get_header(m, "Uniqueid");
01421 
01422    if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
01423       astman_send_error(s, m, "No channel or uniqueid specified");
01424       return 0;
01425    }
01426 
01427    if (!ast_strlen_zero(uniqueid)) {
01428       c = ast_get_channel_by_uniqueid_locked(uniqueid);
01429    } else {
01430        if (!ast_strlen_zero(name))
01431       c = ast_get_channel_by_name_locked(name);
01432    }  
01433 
01434    if (!c) {
01435       astman_send_error(s, m, "No such channel");
01436       return 0;
01437    }
01438    ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
01439    ast_channel_unlock(c);
01440    astman_send_ack(s, m, "Channel Hungup");
01441    return 0;
01442 }

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

References manager_action::action, ast_strlen_zero(), astman_append(), astman_get_header(), manager_action::authority, authority_to_str(), first_action, manager_action::next, manager_action::synopsis, and mansession::writeperm.

Referenced by init_manager().

01361 {
01362    struct manager_action *cur;
01363    char idText[256] = "";
01364    char temp[BUFSIZ];
01365    const char *id = astman_get_header(m,"ActionID");
01366 
01367    if (!ast_strlen_zero(id))
01368       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01369    astman_append(s, "Response: Success\r\n%s", idText);
01370    for (cur = first_action; cur; cur = cur->next) {
01371       if ((s->writeperm & cur->authority) == cur->authority)
01372          astman_append(s, "%s: %s (Priv: %s)\r\n", cur->action, cur->synopsis, authority_to_str(cur->authority, temp, sizeof(temp)));
01373    }
01374    astman_append(s, "\r\n");
01375 
01376    return 0;
01377 }

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

Definition at line 1405 of file manager.c.

References astman_send_response().

Referenced by init_manager().

01406 {
01407    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
01408    return -1;
01409 }

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

Definition at line 2037 of file manager.c.

References ast_app_inboxcount(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and mailbox.

Referenced by init_manager().

02038 {
02039    const char *mailbox = astman_get_header(m, "Mailbox");
02040    const char *id = astman_get_header(m,"ActionID");
02041    char idText[256] = "";
02042    int newmsgs = 0, oldmsgs = 0;
02043    if (ast_strlen_zero(mailbox)) {
02044       astman_send_error(s, m, "Mailbox not specified");
02045       return 0;
02046    }
02047    ast_app_inboxcount(mailbox, &newmsgs, &oldmsgs);
02048    if (!ast_strlen_zero(id)) {
02049       snprintf(idText, sizeof(idText), "ActionID: %s\r\n",id);
02050    }
02051    astman_append(s, "Response: Success\r\n"
02052                "%s"
02053                "Message: Mailbox Message Count\r\n"
02054                "Mailbox: %s\r\n"
02055                "NewMessages: %d\r\n"
02056                "OldMessages: %d\r\n" 
02057                "\r\n",
02058                 idText,mailbox, newmsgs, oldmsgs);
02059    return 0;
02060 }

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

Definition at line 2005 of file manager.c.

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

Referenced by init_manager().

02006 {
02007    const char *mailbox = astman_get_header(m, "Mailbox");
02008    const char *id = astman_get_header(m,"ActionID");
02009    char idText[256] = "";
02010    int ret;
02011    if (ast_strlen_zero(mailbox)) {
02012       astman_send_error(s, m, "Mailbox not specified");
02013       return 0;
02014    }
02015         if (!ast_strlen_zero(id))
02016                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02017    ret = ast_app_has_voicemail(mailbox, NULL);
02018    astman_append(s, "Response: Success\r\n"
02019                "%s"
02020                "Message: Mailbox Status\r\n"
02021                "Mailbox: %s\r\n"
02022                "Waiting: %d\r\n\r\n", idText, mailbox, ret);
02023    return 0;
02024 }

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

Definition at line 1451 of file manager.c.

References ast_send_message(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::data, name, and ast_channel::tech.

Referenced by init_manager().

01452 {
01453    const char *name = astman_get_header(m, "Channel");
01454    const char *from = astman_get_header(m, "From");
01455    const char *message = astman_get_header(m, "Message");
01456    const char *pdu = astman_get_header(m, "PDU");
01457    char tmp[256];
01458    char *tech, *data;
01459    int res;
01460    if (ast_strlen_zero(name) || (ast_strlen_zero(message) && ast_strlen_zero(pdu))) {
01461       astman_send_error(s, m, "No channel or message/PDU specified");
01462       return 0;
01463    }
01464    ast_copy_string(tmp, name, sizeof(tmp));
01465    tech = tmp;
01466    data = strchr(tmp, '/');
01467    if (!data) {
01468       astman_send_error(s, m, "Invalid channel\n");
01469       return 0;
01470    }
01471    *data = '\0';
01472    data++;
01473    if (ast_strlen_zero(pdu)) {
01474        res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)message, 0);
01475    } else {
01476        res = ast_send_message(tech, (char *)data, (char *)name, (char *)from, (char *)pdu, 1);
01477    }
01478    
01479    if (res) {
01480       astman_send_error(s, m, "Error sending message");
01481       return 0;
01482    }
01483    astman_send_ack(s, m, "Message sent");
01484    return 0;
01485 }

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

Definition at line 1867 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, app, fast_originate_helper::appdata, ast_alloc_uniqueid(), ast_callerid_parse(), ast_calloc, ast_cli(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_pbx_outgoing_app2(), ast_pbx_outgoing_exten2(), ast_pthread_create, ast_shrink_phone_number(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_get_variables(), astman_send_error(), fast_originate_helper::callingpres, fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, context, fast_originate_helper::data, ast_channel::data, fast_originate_helper::exten, exten, fast_originate(), mansession::fd, fast_originate_helper::idtext, name, fast_originate_helper::priority, ast_channel::priority, fast_originate_helper::tech, ast_channel::tech, fast_originate_helper::timeout, fast_originate_helper::uniqueid, and fast_originate_helper::vars.

Referenced by init_manager().

01868 {
01869    const char *name = astman_get_header(m, "Channel");
01870    const char *exten = astman_get_header(m, "Exten");
01871    const char *context = astman_get_header(m, "Context");
01872    const char *priority = astman_get_header(m, "Priority");
01873    const char *timeout = astman_get_header(m, "Timeout");
01874    const char *callerid = astman_get_header(m, "CallerID");
01875    const char *account = astman_get_header(m, "Account");
01876    const char *app = astman_get_header(m, "Application");
01877    const char *appdata = astman_get_header(m, "Data");
01878    const char *async = astman_get_header(m, "Async");
01879    const char *id = astman_get_header(m, "ActionID");
01880    const char *callingpres = astman_get_header(m, "CallingPres");
01881    struct ast_variable *vars = astman_get_variables(m);
01882    char *tech, *data;
01883    char *l = NULL, *n = NULL;
01884    int pi = 0;
01885    int res;
01886    int to = 30000;
01887    int reason = 0;
01888    char tmp[256];
01889    char tmp2[256];
01890    char *uniqueid;
01891    int cpresi = 0;
01892    char idText[256] = "";
01893    
01894    pthread_t th;
01895    pthread_attr_t attr;
01896    if (!name) {
01897       astman_send_error(s, m, "Channel not specified");
01898       return 0;
01899    }
01900    if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
01901       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
01902          astman_send_error(s, m, "Invalid priority\n");
01903          return 0;
01904       }
01905    }
01906    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%d", &to) != 1)) {
01907       astman_send_error(s, m, "Invalid timeout\n");
01908       return 0;
01909    }
01910    if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
01911       astman_send_error(s, m, "Invalid CallingPres\n");
01912       return 0;
01913    }
01914    ast_copy_string(tmp, name, sizeof(tmp));
01915    tech = tmp;
01916    data = strchr(tmp, '/');
01917    if (!data) {
01918       astman_send_error(s, m, "Invalid channel\n");
01919       return 0;
01920    }
01921    *data++ = '\0';
01922    ast_copy_string(tmp2, callerid, sizeof(tmp2));
01923    ast_callerid_parse(tmp2, &n, &l);
01924    if (n) {
01925       if (ast_strlen_zero(n))
01926          n = NULL;
01927    }
01928    if (l) {
01929       ast_shrink_phone_number(l);
01930       if (ast_strlen_zero(l))
01931          l = NULL;
01932    }
01933    uniqueid = ast_alloc_uniqueid();
01934    if (ast_true(async)) {
01935       struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
01936       if (!fast) {
01937          res = -1;
01938       } else {
01939          if (!ast_strlen_zero(id))
01940             snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s\r\n", id);
01941          ast_copy_string(fast->tech, tech, sizeof(fast->tech));
01942             ast_copy_string(fast->data, data, sizeof(fast->data));
01943          ast_copy_string(fast->app, app, sizeof(fast->app));
01944          ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
01945          if (l)
01946             ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
01947          if (n)
01948             ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
01949          fast->vars = vars;   
01950          ast_copy_string(fast->context, context, sizeof(fast->context));
01951          ast_copy_string(fast->exten, exten, sizeof(fast->exten));
01952          ast_copy_string(fast->account, account, sizeof(fast->account));
01953          ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
01954          fast->timeout = to;
01955          fast->priority = pi;
01956          fast->callingpres = cpresi;
01957          pthread_attr_init(&attr);
01958          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01959          if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
01960             res = -1;
01961          } else {
01962             res = 0;
01963          }
01964          pthread_attr_destroy(&attr);
01965       }
01966    } else if (!ast_strlen_zero(app)) {
01967          res = ast_pbx_outgoing_app2(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
01968       } else {
01969       if (exten && context && pi)
01970             res = ast_pbx_outgoing_exten2(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
01971       else {
01972          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
01973          return 0;
01974       }
01975    }   
01976    if (!res) {
01977            if (id && !ast_strlen_zero(id)) {
01978                 snprintf(idText,256,"ActionID: %s\r\n",id);
01979       }
01980       ast_cli(s->fd, "Response: Success\r\n"
01981                 "%s"
01982                "Message: Originate successfully queued\r\n"
01983                "Uniqueid: %s\r\n"
01984                "\r\n",
01985                 idText, uniqueid);
01986    } else {
01987       astman_send_error(s, m, "Originate failed");
01988    }
01989    return 0;
01990 }

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

Definition at line 1104 of file manager.c.

References astman_send_response().

Referenced by init_manager().

01105 {
01106    astman_send_response(s, m, "Pong", NULL);
01107    return 0;
01108 }

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

action_redirect: The redirect manager command

Definition at line 1677 of file manager.c.

References ast_async_goto(), ast_channel_unlock, ast_check_hangup(), ast_findlabel_extension(), ast_get_channel_by_name_locked(), ast_get_channel_by_uniqueid_locked(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, and name.

Referenced by init_manager().

01678 {
01679    const char *name = astman_get_header(m, "Channel");
01680    const char *name2 = astman_get_header(m, "ExtraChannel");
01681    const char *exten = astman_get_header(m, "Exten");
01682    const char *context = astman_get_header(m, "Context");
01683    const char *priority = astman_get_header(m, "Priority");
01684    const char *uniqueid = astman_get_header(m, "Uniqueid");
01685    const char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
01686    const char *exten2 = astman_get_header(m, "ExtraExten");
01687    const char *context2 = astman_get_header(m, "ExtraContext");
01688    const char *priority2 = astman_get_header(m, "ExtraPriority");
01689    struct ast_channel *chan, *chan2 = NULL;
01690    int pi = 0;
01691    int pi2 = 0;
01692    int res;
01693 
01694    if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
01695       astman_send_error(s, m, "Channel or Uniqueid not specified");
01696       return 0;
01697    }
01698    if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
01699       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
01700          astman_send_error(s, m, "Invalid priority\n");
01701          return 0;
01702       }
01703    }
01704    /* XXX watch out, possible deadlock!!! */
01705    if (!ast_strlen_zero(uniqueid)) {
01706        chan = ast_get_channel_by_uniqueid_locked(uniqueid);
01707    } else {
01708        chan = ast_get_channel_by_name_locked(name);
01709    }
01710    if (!chan) {
01711       char buf[BUFSIZ];
01712       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
01713       astman_send_error(s, m, buf);
01714       return 0;
01715    }
01716    if (ast_check_hangup(chan)) {
01717       astman_send_error(s, m, "Redirect failed, channel not up.\n");
01718       ast_channel_unlock(chan);
01719       return 0;
01720    }
01721    if (!ast_strlen_zero(name2))
01722       chan2 = ast_get_channel_by_name_locked(name2);
01723    if (chan2 && ast_check_hangup(chan2)) {
01724       astman_send_error(s, m, "Redirect failed, extra channel not up.\n");
01725       ast_channel_unlock(chan);
01726       ast_channel_unlock(chan2);
01727       return 0;
01728    }
01729    res = ast_async_goto(chan, context, exten, pi);
01730    if (!res) {
01731       if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
01732          if (chan2)
01733             res = ast_async_goto(chan2, context2, exten2, pi2);
01734          else
01735             res = -1;
01736          if (!res)
01737             astman_send_ack(s, m, "Dual Redirect successful");
01738          else
01739             astman_send_error(s, m, "Secondary redirect failed");
01740       } else
01741          astman_send_ack(s, m, "Redirect successful");
01742    } else
01743       astman_send_error(s, m, "Redirect failed");
01744    if (chan)
01745       ast_channel_unlock(chan);
01746    if (chan2)
01747       ast_channel_unlock(chan2);
01748    return 0;
01749 }

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

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

01495 {
01496         struct ast_channel *c = NULL;
01497    const char *name = astman_get_header(m, "Channel");
01498    const char *varname = astman_get_header(m, "Variable");
01499    const char *varval = astman_get_header(m, "Value");
01500    
01501    if (ast_strlen_zero(varname)) {
01502       astman_send_error(s, m, "No variable specified");
01503       return 0;
01504    }
01505    
01506    if (!ast_strlen_zero(name)) {
01507       c = ast_get_channel_by_name_locked(name);
01508       if (!c) {
01509          astman_send_error(s, m, "No such channel");
01510          return 0;
01511       }
01512    }
01513    
01514    pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
01515      
01516    if (c)
01517       ast_channel_unlock(c);
01518 
01519    astman_send_ack(s, m, "Variable Set"); 
01520 
01521    return 0;
01522 }

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

Manager "status" command to show channels.

Definition at line 1576 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, ast_channel_unlock, ast_channel_walk_locked(), ast_get_channel_by_name_locked(), ast_state2str(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, name, ast_channel::pbx, ast_channel::priority, S_OR, and ast_cdr::start.

Referenced by init_manager().

01577 {
01578    const char *id = astman_get_header(m,"ActionID");
01579       const char *name = astman_get_header(m,"Channel");
01580    char idText[256] = "";
01581    struct ast_channel *c;
01582    char bridge[256];
01583    struct timeval now = ast_tvnow();
01584    long elapsed_seconds = 0;
01585    int all = ast_strlen_zero(name); /* set if we want all channels */
01586 
01587    if (!ast_strlen_zero(id))
01588       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01589    if (all)
01590       c = ast_channel_walk_locked(NULL);
01591    else {
01592       c = ast_get_channel_by_name_locked(name);
01593       if (!c) {
01594          astman_send_error(s, m, "No such channel");
01595          return 0;
01596       }
01597    }
01598    astman_send_ack(s, m, "Channel status will follow");
01599    /* if we look by name, we break after the first iteration */
01600    while (c) {
01601       if (c->_bridge)
01602          snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->_bridge->name);
01603       else
01604          bridge[0] = '\0';
01605       if (c->pbx) {
01606          if (c->cdr) {
01607             elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01608          }
01609          astman_append(s,
01610          "Event: Status\r\n"
01611          "Privilege: Call\r\n"
01612          "Channel: %s\r\n"
01613          "CallerID: %s\r\n"      /* This parameter is deprecated and will be removed post-1.4 */
01614          "CallerIDNum: %s\r\n"
01615          "CallerIDName: %s\r\n"
01616          "Account: %s\r\n"
01617          "State: %s\r\n"
01618          "Context: %s\r\n"
01619          "Extension: %s\r\n"
01620          "Priority: %d\r\n"
01621          "Seconds: %ld\r\n"
01622          "%s"
01623          "Uniqueid: %s\r\n"
01624          "%s"
01625          "\r\n",
01626          c->name, 
01627          S_OR(c->cid.cid_num, "<unknown>"), 
01628          S_OR(c->cid.cid_num, "<unknown>"), 
01629          S_OR(c->cid.cid_name, "<unknown>"), 
01630          c->accountcode,
01631          ast_state2str(c->_state), c->context,
01632          c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, idText);
01633       } else {
01634          astman_append(s,
01635          "Event: Status\r\n"
01636          "Privilege: Call\r\n"
01637          "Channel: %s\r\n"
01638          "CallerID: %s\r\n"      /* This parameter is deprecated and will be removed post-1.4 */
01639          "CallerIDNum: %s\r\n"
01640          "CallerIDName: %s\r\n"
01641          "Account: %s\r\n"
01642          "State: %s\r\n"
01643          "%s"
01644          "Uniqueid: %s\r\n"
01645          "%s"
01646          "\r\n",
01647          c->name, 
01648          S_OR(c->cid.cid_num, "<unknown>"), 
01649          S_OR(c->cid.cid_num, "<unknown>"), 
01650          S_OR(c->cid.cid_name, "<unknown>"), 
01651          c->accountcode,
01652          ast_state2str(c->_state), bridge, c->uniqueid, idText);
01653       }
01654       ast_channel_unlock(c);
01655       if (!all)
01656          break;
01657       c = ast_channel_walk_locked(c);
01658    }
01659    astman_append(s,
01660    "Event: StatusComplete\r\n"
01661    "%s"
01662    "\r\n",idText);
01663    return 0;
01664 }

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

Definition at line 2110 of file manager.c.

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

02111 {
02112    struct ast_channel *c = NULL;
02113    const char *name = astman_get_header(m, "Channel");
02114    int timeout = atoi(astman_get_header(m, "Timeout"));
02115    if (ast_strlen_zero(name)) {
02116       astman_send_error(s, m, "No channel specified");
02117       return 0;
02118    }
02119    if (!timeout) {
02120       astman_send_error(s, m, "No timeout specified");
02121       return 0;
02122    }
02123    c = ast_get_channel_by_name_locked(name);
02124    if (!c) {
02125       astman_send_error(s, m, "No such channel");
02126       return 0;
02127    }
02128    ast_channel_setwhentohangup(c, timeout);
02129    ast_channel_unlock(c);
02130    astman_send_ack(s, m, "Timeout Set");
02131    return 0;
02132 }

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

Definition at line 1227 of file manager.c.

References ast_config_destroy(), ast_config_load_with_comments(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_append(), astman_get_header(), astman_send_error(), config_text_file_save(), and handle_updates().

Referenced by init_manager().

01228 {
01229    struct ast_config *cfg;
01230    const char *sfn = astman_get_header(m, "SrcFilename");
01231    const char *dfn = astman_get_header(m, "DstFilename");
01232    int res;
01233    char idText[256] = "";
01234    const char *id = astman_get_header(m, "ActionID");
01235    const char *rld = astman_get_header(m, "Reload");
01236 
01237    if (!ast_strlen_zero(id))
01238       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01239 
01240    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
01241       astman_send_error(s, m, "Filename not specified");
01242       return 0;
01243    }
01244    if (!(cfg = ast_config_load_with_comments(sfn))) {
01245       astman_send_error(s, m, "Config file not found");
01246       return 0;
01247    }
01248    handle_updates(s, m, cfg);
01249    res = config_text_file_save(dfn, cfg, "Manager");
01250    ast_config_destroy(cfg);
01251    if (res) {
01252       astman_send_error(s, m, "Save of config failed");
01253       return 0;
01254    }
01255    astman_append(s, "Response: Success\r\n%s\r\n", idText);
01256    if (!ast_strlen_zero(rld)) {
01257       if (ast_true(rld))
01258          rld = NULL;
01259       ast_module_reload(rld); 
01260    }
01261    return 0;
01262 }

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

Definition at line 2167 of file manager.c.

References astman_get_header(), event, EVENT_FLAG_USER, message::hdrcount, message::headers, and manager_event().

Referenced by init_manager().

02168 {
02169    const char *event = astman_get_header(m, "UserEvent");
02170    char body[2048] = "";
02171    int x, bodylen = 0;
02172    for (x = 0; x < m->hdrcount; x++) {
02173       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
02174          ast_copy_string(body + bodylen, m->headers[x], sizeof(body) - bodylen - 3);
02175          bodylen += strlen(m->headers[x]);
02176          ast_copy_string(body + bodylen, "\r\n", 3);
02177          bodylen += 2;
02178       }
02179    }
02180 
02181    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, body);
02182    return 0;
02183 }

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

Definition at line 1272 of file manager.c.

References mansession::__lock, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_strlen_zero(), ast_wait_for_input(), astman_append(), astman_get_header(), astman_send_response(), eventqent::category, eventqent::eventdata, mansession::eventq, mansession::fd, LOG_DEBUG, mansession::needdestroy, eventqent::next, option_debug, mansession::readperm, mansession::send_events, mansession::sessiontimeout, unuse_eventqent(), and mansession::waiting_thread.

Referenced by init_manager().

01273 {
01274    const char *timeouts = astman_get_header(m, "Timeout");
01275    int timeout = -1, max;
01276    int x;
01277    int needexit = 0;
01278    time_t now;
01279    struct eventqent *eqe;
01280    const char *id = astman_get_header(m,"ActionID");
01281    char idText[256] = "";
01282 
01283    if (!ast_strlen_zero(id))
01284       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01285 
01286    if (!ast_strlen_zero(timeouts)) {
01287       sscanf(timeouts, "%i", &timeout);
01288    }
01289    
01290    ast_mutex_lock(&s->__lock);
01291    if (s->waiting_thread != AST_PTHREADT_NULL) {
01292       pthread_kill(s->waiting_thread, SIGURG);
01293    }
01294    if (s->sessiontimeout) {
01295       time(&now);
01296       max = s->sessiontimeout - now - 10;
01297       if (max < 0)
01298          max = 0;
01299       if ((timeout < 0) || (timeout > max))
01300          timeout = max;
01301       if (!s->send_events)
01302          s->send_events = -1;
01303       /* Once waitevent is called, always queue events from now on */
01304    }
01305    ast_mutex_unlock(&s->__lock);
01306    s->waiting_thread = pthread_self();
01307    if (option_debug)
01308       ast_log(LOG_DEBUG, "Starting waiting for an event!\n");
01309    for (x=0; ((x < timeout) || (timeout < 0)); x++) {
01310       ast_mutex_lock(&s->__lock);
01311       if (s->eventq && s->eventq->next)
01312          needexit = 1;
01313       if (s->waiting_thread != pthread_self())
01314          needexit = 1;
01315       if (s->needdestroy)
01316          needexit = 1;
01317       ast_mutex_unlock(&s->__lock);
01318       if (needexit)
01319          break;
01320       if (s->fd > 0) {
01321          if (ast_wait_for_input(s->fd, 1000))
01322             break;
01323       } else {
01324          sleep(1);
01325       }
01326    }
01327    if (option_debug)
01328       ast_log(LOG_DEBUG, "Finished waiting for an event!\n");
01329    ast_mutex_lock(&s->__lock);
01330    if (s->waiting_thread == pthread_self()) {
01331       astman_send_response(s, m, "Success", "Waiting for Event...");
01332       /* Only show events if we're the most recent waiter */
01333       while(s->eventq->next) {
01334          eqe = s->eventq->next;
01335          if (((s->readperm & eqe->category) == eqe->category) &&
01336              ((s->send_events & eqe->category) == eqe->category)) {
01337             astman_append(s, "%s", eqe->eventdata);
01338          }
01339          unuse_eventqent(s->eventq);
01340          s->eventq = eqe;
01341       }
01342       astman_append(s,
01343          "Event: WaitEventComplete\r\n"
01344          "%s"
01345          "\r\n", idText);
01346       s->waiting_thread = AST_PTHREADT_NULL;
01347    } else {
01348       ast_log(LOG_DEBUG, "Abandoning event request!\n");
01349    }
01350    ast_mutex_unlock(&s->__lock);
01351    return 0;
01352 }

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

Definition at line 2488 of file manager.c.

References ast_malloc, eventqent::category, eventqent::eventdata, eventqent::next, and eventqent::usecount.

Referenced by init_manager(), and manager_event().

02489 {
02490    struct eventqent *tmp, *prev = NULL;
02491    tmp = ast_malloc(sizeof(*tmp) + strlen(str));
02492 
02493    if (!tmp)
02494       return -1;
02495 
02496    tmp->next = NULL;
02497    tmp->category = category;
02498    strcpy(tmp->eventdata, str);
02499    
02500    if (master_eventq) {
02501       prev = master_eventq;
02502       while (prev->next) 
02503          prev = prev->next;
02504       prev->next = tmp;
02505    } else {
02506       master_eventq = tmp;
02507    }
02508    
02509    tmp->usecount = num_sessions;
02510    
02511    return 0;
02512 }

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

Definition at line 473 of file manager.c.

References AST_LIST_TRAVERSE, ast_manager_user::username, and users.

Referenced by handle_showmanager(), and init_manager().

00474 {
00475    struct ast_manager_user *user = NULL;
00476 
00477    AST_LIST_TRAVERSE(&users, user, list)
00478       if (!strcasecmp(user->username, name))
00479          break;
00480    return user;
00481 }

static int ast_instring ( const char *  bigstr,
const char *  smallstr,
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 860 of file manager.c.

References ast_variable::next.

Referenced by get_perm(), and strings_to_mask().

00861 {
00862    const char *val = bigstr, *next;
00863 
00864    do {
00865       if ((next = strchr(val, delim))) {
00866          if (!strncmp(val, smallstr, (next - val)))
00867             return 1;
00868          else
00869             continue;
00870       } else
00871          return !strcmp(smallstr, val);
00872 
00873    } while (*(val = (next + 1)));
00874 
00875    return 0;
00876 }

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

Definition at line 893 of file manager.c.

Referenced by strings_to_mask().

00894 {
00895    int ret = 1, x = 0;
00896 
00897    if (!string)
00898       return 0;
00899 
00900    for (x = 0; x < strlen(string); x++) {
00901       if (!(string[x] >= 48 && string[x] <= 57)) {
00902          ret = 0;
00903          break;
00904       }
00905    }
00906    
00907    return ret ? atoi(string) : 0;
00908 }

static AST_LIST_HEAD_STATIC ( users  ,
ast_manager_user   
) [static]

static AST_LIST_HEAD_STATIC ( sessions  ,
mansession   
) [static]

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

register a 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

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

Definition at line 2636 of file manager.c.

References manager_action::action, ast_malloc, ast_manager_register_struct(), manager_action::authority, manager_action::description, func, manager_action::func, manager_action::next, and manager_action::synopsis.

Referenced by init_manager(), and load_module().

02637 {
02638    struct manager_action *cur;
02639 
02640    cur = ast_malloc(sizeof(*cur));
02641    if (!cur)
02642       return -1;
02643    
02644    cur->action = action;
02645    cur->authority = auth;
02646    cur->func = func;
02647    cur->synopsis = synopsis;
02648    cur->description = description;
02649    cur->next = NULL;
02650 
02651    ast_manager_register_struct(cur);
02652 
02653    return 0;
02654 }

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 2592 of file manager.c.

References manager_action::action, ast_log(), ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_verbose(), first_action, LOG_WARNING, manager_action::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by ast_manager_register2().

02593 {
02594    struct manager_action *cur, *prev = NULL;
02595    int ret;
02596 
02597    ast_rwlock_wrlock(&actionlock);
02598    cur = first_action;
02599    while (cur) { /* Walk the list of actions */
02600       ret = strcasecmp(cur->action, act->action);
02601       if (ret == 0) {
02602          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
02603          ast_rwlock_unlock(&actionlock);
02604          return -1;
02605       } else if (ret > 0) {
02606          /* Insert these alphabetically */
02607          if (prev) {
02608             act->next = prev->next;
02609             prev->next = act;
02610          } else {
02611             act->next = first_action;
02612             first_action = act;
02613          }
02614          break;
02615       }
02616       prev = cur; 
02617       cur = cur->next;
02618    }
02619    
02620    if (!cur) {
02621       if (prev)
02622          prev->next = act;
02623       else
02624          first_action = act;
02625       act->next = NULL;
02626    }
02627 
02628    if (option_verbose > 1) 
02629       ast_verbose(VERBOSE_PREFIX_2 "Manager registered action %s\n", act->action);
02630    ast_rwlock_unlock(&actionlock);
02631    return 0;
02632 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registred manager command

Parameters:
action Name of registred Action:

Definition at line 2561 of file manager.c.

References manager_action::action, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_verbose(), first_action, free, manager_action::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and unload_module().

02562 {
02563    struct manager_action *cur, *prev;
02564 
02565    ast_rwlock_wrlock(&actionlock);
02566    cur = prev = first_action;
02567    while (cur) {
02568       if (!strcasecmp(action, cur->action)) {
02569          prev->next = cur->next;
02570          free(cur);
02571          if (option_verbose > 1) 
02572             ast_verbose(VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action);
02573          ast_rwlock_unlock(&actionlock);
02574          return 0;
02575       }
02576       prev = cur;
02577       cur = cur->next;
02578    }
02579    ast_rwlock_unlock(&actionlock);
02580    return 0;
02581 }

AST_RWLOCK_DEFINE_STATIC ( actionlock   ) 

AST_THREADSTORAGE ( astman_append_buf  ,
astman_append_buf_init   
)

AST_THREADSTORAGE ( manager_event_buf  ,
manager_event_buf_init   
)

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

Definition at line 483 of file manager.c.

References mansession::__lock, ast_calloc, ast_carefulwrite(), ast_dynamic_str_thread_set_va, ast_mutex_lock(), ast_mutex_unlock(), ASTMAN_APPEND_BUF_INITSIZE, mansession::fd, mansession::outputstr, and mansession::writetimeout.

Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peer(), _sip_show_peers(), action_agents(), action_command(), action_devstate(), action_extensionstate(), action_getconfig(), action_getvar(), action_listcommands(), action_mailboxcount(), action_mailboxstatus(), action_status(), action_updateconfig(), action_waitevent(), action_zapshowchannels(), ast_cli_netstats(), astman_send_error(), astman_send_response(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peers(), manager_jabber_send(), manager_parking_status(), manager_queues_show(), manager_queues_status(), manager_sip_show_peer(), manager_sip_show_peers(), process_message(), and session_do().

00484 {
00485    va_list ap;
00486    struct ast_dynamic_str *buf;
00487 
00488    ast_mutex_lock(&s->__lock);
00489 
00490    if (!(buf = ast_dynamic_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
00491       ast_mutex_unlock(&s->__lock);
00492       return;
00493    }
00494 
00495    va_start(ap, fmt);
00496    ast_dynamic_str_thread_set_va(&buf, 0, &astman_append_buf, fmt, ap);
00497    va_end(ap);
00498    
00499    if (s->fd > -1)
00500       ast_carefulwrite(s->fd, buf->str, strlen(buf->str), s->writetimeout);
00501    else {
00502       if (!s->outputstr && !(s->outputstr = ast_calloc(1, sizeof(*s->outputstr)))) {
00503          ast_mutex_unlock(&s->__lock);
00504          return;
00505       }
00506 
00507       ast_dynamic_str_append(&s->outputstr, 0, "%s", buf->str);   
00508    }
00509 
00510    ast_mutex_unlock(&s->__lock);
00511 }

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

Get header from mananger transaction

Definition at line 763 of file manager.c.

References message::hdrcount, and message::headers.

Referenced by _sip_show_peer(), _sip_show_peers(), action_agent_callback_login(), action_agent_logoff(), action_agents(), action_command(), action_devstate(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_mailboxcount(), action_mailboxstatus(), action_message(), action_originate(), action_redirect(), action_setcdruserfield(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), action_zapdialoffhook(), action_zapdndoff(), action_zapdndon(), action_zapshowchannels(), astman_send_error(), astman_send_response(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_dbdel(), manager_dbget(), manager_dbput(), manager_iax2_show_peers(), manager_jabber_send(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queues_status(), manager_remove_queue_member(), manager_sip_show_peer(), manager_sip_show_peers(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().

00764 {
00765    char cmp[80];
00766    int x;
00767 
00768    snprintf(cmp, sizeof(cmp), "%s: ", var);
00769 
00770    for (x = 0; x < m->hdrcount; x++) {
00771       if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
00772          return m->headers[x] + strlen(cmp);
00773    }
00774 
00775    return "";
00776 }

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

Get a linked list of the Variable: headers

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

00779 {
00780    int varlen, x, y;
00781    struct ast_variable *head = NULL, *cur;
00782    char *var, *val;
00783 
00784    char *parse;    
00785    AST_DECLARE_APP_ARGS(args,
00786       AST_APP_ARG(vars)[32];
00787    );
00788 
00789    varlen = strlen("Variable: ");   
00790 
00791    for (x = 0; x < m->hdrcount; x++) {
00792       if (strncasecmp("Variable: ", m->headers[x], varlen))
00793          continue;
00794 
00795       parse = ast_strdupa(m->headers[x] + varlen);
00796 
00797       AST_STANDARD_APP_ARGS(args, parse);
00798       if (args.argc) {
00799          for (y = 0; y < args.argc; y++) {
00800             if (!args.vars[y])
00801                continue;
00802             var = val = ast_strdupa(args.vars[y]);
00803             strsep(&val, "=");
00804             if (!val || ast_strlen_zero(var))
00805                continue;
00806             cur = ast_variable_new(var, val);
00807             if (head) {
00808                cur->next = head;
00809                head = cur;
00810             } else
00811                head = cur;
00812          }
00813       }
00814    }
00815 
00816    return head;
00817 }

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 
)

Note:
NOTE: 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->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.

Definition at line 827 of file manager.c.

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

Referenced by _sip_show_peer(), action_agent_callback_login(), action_agent_logoff(), action_command(), action_devstate(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_mailboxcount(), action_mailboxstatus(), action_message(), action_originate(), action_redirect(), action_setcdruserfield(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_zapdialoffhook(), action_zapdndoff(), action_zapdndon(), action_zaprestart(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_remove_queue_member(), manager_sip_show_peer(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().

00828 {
00829    const char *id = astman_get_header(m,"ActionID");
00830 
00831    astman_append(s, "Response: Error\r\n");
00832    if (!ast_strlen_zero(id))
00833       astman_append(s, "ActionID: %s\r\n", id);
00834    astman_append(s, "Message: %s\r\n\r\n", error);
00835 }

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

Definition at line 837 of file manager.c.

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

Referenced by action_events(), action_logoff(), action_ping(), action_waitevent(), and astman_send_ack().

00838 {
00839    const char *id = astman_get_header(m,"ActionID");
00840 
00841    astman_append(s, "Response: %s\r\n", resp);
00842    if (!ast_strlen_zero(id))
00843       astman_append(s, "ActionID: %s\r\n", id);
00844    if (msg)
00845       astman_append(s, "Message: %s\r\n\r\n", msg);
00846    else
00847       astman_append(s, "\r\n");
00848 }

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

Definition at line 953 of file manager.c.

References ast_append_ha(), ast_apply_ha(), ast_category_browse(), ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_load(), ast_free_ha(), ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), astman_get_header(), mansession::challenge, mansession::displaysystemname, events, get_perm(), key(), len, ast_variable::lineno, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MD5Final(), MD5Init(), MD5Update(), ast_variable::name, ast_variable::next, password, mansession::readperm, S_OR, set_eventmask(), mansession::sin, mansession::username, ast_variable::value, mansession::writeperm, and mansession::writetimeout.

Referenced by authenticate_reply(), handle_response_invite(), process_message(), and registry_rerequest().

00954 {
00955    struct ast_config *cfg;
00956    char *cat;
00957    const char *user = astman_get_header(m, "Username");
00958    const char *pass = astman_get_header(m, "Secret");
00959    const char *authtype = astman_get_header(m, "AuthType");
00960    const char *key = astman_get_header(m, "Key");
00961    const char *events = astman_get_header(m, "Events");
00962    
00963    cfg = ast_config_load("manager.conf");
00964    if (!cfg)
00965       return -1;
00966    cat = ast_category_browse(cfg, NULL);
00967    while (cat) {
00968       if (strcasecmp(cat, "general")) {
00969          /* This is a user */
00970          if (!strcasecmp(cat, user)) {
00971             struct ast_variable *v;
00972             struct ast_ha *ha = NULL;
00973             char *password = NULL;
00974 
00975             for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
00976                if (!strcasecmp(v->name, "secret")) {
00977                   password = v->value;
00978                } else if (!strcasecmp(v->name, "displaysystemname")) {
00979                   if (ast_true(v->value)) {
00980                      if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
00981                         s->displaysystemname = 1;
00982                      } else {
00983                         ast_log(LOG_ERROR, "Can't enable displaysystemname in manager.conf - no system name configured in asterisk.conf\n");
00984                      }
00985                   }
00986                } else if (!strcasecmp(v->name, "permit") ||
00987                      !strcasecmp(v->name, "deny")) {
00988                   ha = ast_append_ha(v->name, v->value, ha);
00989                } else if (!strcasecmp(v->name, "writetimeout")) {
00990                   int val = atoi(v->value);
00991 
00992                   if (val < 100)
00993                      ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", v->value, v->lineno);
00994                   else
00995                      s->writetimeout = val;
00996                }
00997                      
00998             }
00999             if (ha && !ast_apply_ha(ha, &(s->sin))) {
01000                ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
01001                ast_free_ha(ha);
01002                ast_config_destroy(cfg);
01003                return -1;
01004             } else if (ha)
01005                ast_free_ha(ha);
01006             if (!strcasecmp(authtype, "MD5")) {
01007                if (!ast_strlen_zero(key) && 
01008                    !ast_strlen_zero(s->challenge) && !ast_strlen_zero(password)) {
01009                   int x;
01010                   int len = 0;
01011                   char md5key[256] = "";
01012                   struct MD5Context md5;
01013                   unsigned char digest[16];
01014                   MD5Init(&md5);
01015                   MD5Update(&md5, (unsigned char *) s->challenge, strlen(s->challenge));
01016                   MD5Update(&md5, (unsigned char *) password, strlen(password));
01017                   MD5Final(digest, &md5);
01018                   for (x=0; x<16; x++)
01019                      len += sprintf(md5key + len, "%2.2x", digest[x]);
01020                   if (!strcmp(md5key, key))
01021                      break;
01022                   else {
01023                      ast_config_destroy(cfg);
01024                      return -1;
01025                   }
01026                } else {
01027                   ast_log(LOG_DEBUG, "MD5 authentication is not possible.  challenge: '%s'\n", 
01028                      S_OR(s->challenge, ""));
01029                   ast_config_destroy(cfg);
01030                   return -1;
01031                }
01032             } else if (password && !strcmp(password, pass)) {
01033                break;
01034             } else {
01035                ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
01036                ast_config_destroy(cfg);
01037                return -1;
01038             }  
01039          }
01040       }
01041       cat = ast_category_browse(cfg, cat);
01042    }
01043    if (cat) {
01044       ast_copy_string(s->username, cat, sizeof(s->username));
01045       s->readperm = get_perm(ast_variable_retrieve(cfg, cat, "read"));
01046       s->writeperm = get_perm(ast_variable_retrieve(cfg, cat, "write"));
01047       ast_config_destroy(cfg);
01048       if (events)
01049          set_eventmask(s, events);
01050       return 0;
01051    }
01052    ast_config_destroy(cfg);
01053    cfg = ast_config_load("users.conf");
01054    if (!cfg)
01055       return -1;
01056    cat = ast_category_browse(cfg, NULL);
01057    while (cat) {
01058       struct ast_variable *v;
01059       const char *password = NULL;
01060       int hasmanager = 0;
01061       const char *readperms = NULL;
01062       const char *writeperms = NULL;
01063 
01064       if (strcasecmp(cat, user) || !strcasecmp(cat, "general")) {
01065          cat = ast_category_browse(cfg, cat);
01066          continue;
01067       }
01068       for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
01069          if (!strcasecmp(v->name, "secret"))
01070             password = v->value;
01071          else if (!strcasecmp(v->name, "hasmanager"))
01072             hasmanager = ast_true(v->value);
01073          else if (!strcasecmp(v->name, "managerread"))
01074             readperms = v->value;
01075          else if (!strcasecmp(v->name, "managerwrite"))
01076             writeperms = v->value;
01077       }
01078       if (!hasmanager)
01079          break;
01080       if (!password || strcmp(password, pass)) {
01081          ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
01082          ast_config_destroy(cfg);
01083          return -1;
01084       }
01085       ast_copy_string(s->username, cat, sizeof(s->username));
01086       s->readperm = readperms ? get_perm(readperms) : -1;
01087       s->writeperm = writeperms ? get_perm(writeperms) : -1;
01088       ast_config_destroy(cfg);
01089       if (events)
01090          set_eventmask(s, events);
01091       return 0;
01092    }
01093    ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
01094    ast_config_destroy(cfg);
01095    return -1;
01096 }

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

Convert authority code to string with serveral options.

Definition at line 207 of file manager.c.

References ast_strlen_zero(), and perms.

Referenced by action_listcommands(), handle_showmancmd(), handle_showmancmds(), and manager_event().

00208 {
00209    int running_total = 0, i;
00210 
00211    memset(res, 0, reslen);
00212    for (i = 0; i < (sizeof(perms) / sizeof(perms[0])) - 1; i++) {
00213       if (authority & perms[i].num) {
00214          if (*res) {
00215             strncat(res, ",", (reslen > running_total) ? reslen - running_total : 0);
00216             running_total++;
00217          }
00218          strncat(res, perms[i].label, (reslen > running_total) ? reslen - running_total : 0);
00219          running_total += strlen(perms[i].label);
00220       }
00221    }
00222 
00223    if (ast_strlen_zero(res))
00224       ast_copy_string(res, "<none>", reslen);
00225    
00226    return res;
00227 }

static char* complete_show_mancmd ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 229 of file manager.c.

References manager_action::action, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strdup, first_action, and manager_action::next.

00230 {
00231    struct manager_action *cur;
00232    int which = 0;
00233    char *ret = NULL;
00234 
00235    ast_rwlock_rdlock(&actionlock);
00236    for (cur = first_action; cur; cur = cur->next) { /* Walk the list of actions */
00237       if (!strncasecmp(word, cur->action, strlen(word)) && ++which > state) {
00238          ret = ast_strdup(cur->action);
00239          break;   /* make sure we exit even if ast_strdup() returns NULL */
00240       }
00241    }
00242    ast_rwlock_unlock(&actionlock);
00243 
00244    return ret;
00245 }

static int compress_char ( char  c  )  [static]

Definition at line 289 of file manager.c.

Referenced by member_hash_fn(), and variable_count_hash_fn().

00290 {
00291    c &= 0x7f;
00292    if (c < 32)
00293       return 0;
00294    else if (c >= 'a' && c <= 'z')
00295       return c - 64;
00296    else if (c > 'z')
00297       return '_';
00298    else
00299       return c - 32;
00300 }

static void destroy_session ( struct mansession s  )  [static]

Definition at line 754 of file manager.c.

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

Referenced by accept_thread(), generic_http_callback(), session_do(), and skinny_session().

00755 {
00756    AST_LIST_LOCK(&sessions);
00757    AST_LIST_REMOVE(&sessions, s, list);
00758    num_sessions--;
00759    free_session(s);
00760    AST_LIST_UNLOCK(&sessions);
00761 }

static int do_message ( struct mansession s  )  [static]

Definition at line 2321 of file manager.c.

References AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), mansession::eventq, get_input(), message::hdrcount, message::headers, mansession::inbuf, eventqent::next, process_events(), and process_message().

Referenced by session_do().

02322 {
02323    struct message m = { 0 };
02324    char header_buf[sizeof(s->inbuf)] = { '\0' };
02325    int res;
02326 
02327    for (;;) {
02328       /* Check if any events are pending and do them if needed */
02329       if (s->eventq->next) {
02330          if (process_events(s))
02331             return -1;
02332       }
02333       res = get_input(s, header_buf);
02334       if (res == 0) {
02335          continue;
02336       } else if (res > 0) {
02337          /* Strip trailing \r\n */
02338          if (strlen(header_buf) < 2)
02339             continue;
02340          header_buf[strlen(header_buf) - 2] = '\0';
02341          if (ast_strlen_zero(header_buf))
02342             return process_message(s, &m) ? -1 : 0;
02343          else if (m.hdrcount < (AST_MAX_MANHEADERS - 1))
02344             m.headers[m.hdrcount++] = ast_strdupa(header_buf);
02345       } else {
02346          return res;
02347       }
02348    }
02349 }

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

Definition at line 1803 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, AST_FORMAT_SLINEAR, ast_pbx_outgoing_app2(), ast_pbx_outgoing_exten2(), ast_strlen_zero(), fast_originate_helper::callingpres, 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, free, fast_originate_helper::idtext, manager_event(), fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, fast_originate_helper::uniqueid, and fast_originate_helper::vars.

Referenced by action_originate().

01804 {
01805    struct fast_originate_helper *in = data;
01806    int res;
01807    int reason = 0;
01808    struct ast_channel *chan = NULL;
01809    char requested_channel[AST_CHANNEL_NAME];
01810 
01811    if (!ast_strlen_zero(in->app)) {
01812       res = ast_pbx_outgoing_app2(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
01813          S_OR(in->cid_num, NULL), 
01814          S_OR(in->cid_name, NULL),
01815          in->vars, in->account, &chan, in->uniqueid);
01816    } else {
01817       res = ast_pbx_outgoing_exten2(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
01818          S_OR(in->cid_num, NULL), 
01819          S_OR(in->cid_name, NULL),
01820          in->vars, in->account, &chan, in->uniqueid);
01821    }
01822 
01823    if (!chan)
01824       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);   
01825    /* Tell the manager what happened with the channel */
01826    manager_event(EVENT_FLAG_CALL, "OriginateResponse",
01827       "%s"
01828       "Response: %s\r\n"
01829       "Channel: %s\r\n"
01830       "Context: %s\r\n"
01831       "Exten: %s\r\n"
01832       "Reason: %d\r\n"
01833       "Uniqueid: %s\r\n"
01834       "CallerID: %s\r\n"      /* This parameter is deprecated and will be removed post-1.4 */
01835       "CallerIDNum: %s\r\n"
01836       "CallerIDName: %s\r\n",
01837       in->idtext, res ? "Failure" : "Success", chan ? chan->name : requested_channel, in->context, in->exten, reason, 
01838       chan ? chan->uniqueid : "<null>",
01839       S_OR(in->cid_num, "<unknown>"),
01840       S_OR(in->cid_num, "<unknown>"),
01841       S_OR(in->cid_name, "<unknown>")
01842       );
01843 
01844    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
01845    if (chan)
01846       ast_channel_unlock(chan);
01847    free(in);
01848    return NULL;
01849 }

static void free_session ( struct mansession s  )  [static]

Definition at line 738 of file manager.c.

References mansession::__lock, ast_mutex_destroy(), mansession::eventq, mansession::fd, free, eventqent::next, mansession::outputstr, and unuse_eventqent().

Referenced by accept_thread(), and destroy_session().

00739 {
00740    struct eventqent *eqe;
00741    if (s->fd > -1)
00742       close(s->fd);
00743    if (s->outputstr)
00744       free(s->outputstr);
00745    ast_mutex_destroy(&s->__lock);
00746    while (s->eventq) {
00747       eqe = s->eventq;
00748       s->eventq = s->eventq->next;
00749       unuse_eventqent(eqe);
00750    }
00751    free(s);
00752 }

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

Definition at line 2267 of file manager.c.

References mansession::__lock, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, errno, pollfd::events, mansession::fd, pollfd::fd, ast_channel::fds, mansession::inbuf, mansession::inlen, LOG_WARNING, poll(), POLLIN, mansession::sin, and mansession::waiting_thread.

Referenced by do_message(), and skinny_session().

02268 {
02269    /* output must have at least sizeof(s->inbuf) space */
02270    int res;
02271    int x;
02272    struct pollfd fds[1];
02273    for (x = 1; x < s->inlen; x++) {
02274       if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
02275          /* Copy output data up to and including \r\n */
02276          memcpy(output, s->inbuf, x + 1);
02277          /* Add trailing \0 */
02278          output[x+1] = '\0';
02279          /* Move remaining data back to the front */
02280          memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
02281          s->inlen -= (x + 1);
02282          return 1;
02283       }
02284    } 
02285    if (s->inlen >= sizeof(s->inbuf) - 1) {
02286       ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->sin.sin_addr), s->inbuf);
02287       s->inlen = 0;
02288    }
02289    fds[0].fd = s->fd;
02290    fds[0].events = POLLIN;
02291    do {
02292       ast_mutex_lock(&s->__lock);
02293       s->waiting_thread = pthread_self();
02294       ast_mutex_unlock(&s->__lock);
02295 
02296       res = poll(fds, 1, -1);
02297 
02298       ast_mutex_lock(&s->__lock);
02299       s->waiting_thread = AST_PTHREADT_NULL;
02300       ast_mutex_unlock(&s->__lock);
02301       if (res < 0) {
02302          if (errno == EINTR) {
02303             return 0;
02304          }
02305          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
02306          return -1;
02307       } else if (res > 0) {
02308          ast_mutex_lock(&s->__lock);
02309          res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
02310          ast_mutex_unlock(&s->__lock);
02311          if (res < 1)
02312             return -1;
02313          break;
02314       }
02315    } while(1);
02316    s->inlen += res;
02317    s->inbuf[s->inlen] = '\0';
02318    return 0;
02319 }

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

Definition at line 878 of file manager.c.

References ast_instring(), and perms.

Referenced by authenticate().

00879 {
00880    int x = 0, ret = 0;
00881 
00882    if (!instr)
00883       return 0;
00884 
00885    for (x = 0; x < (sizeof(perms) / sizeof(perms[0])); x++) {
00886       if (ast_instring(instr, perms[x].label, ','))
00887          ret |= perms[x].num;
00888    }
00889    
00890    return ret;
00891 }

static int handle_showmanager ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 535 of file manager.c.

References ast_cli(), ast_get_manager_by_name_locked(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_manager_user::deny, ast_manager_user::displayconnects, ast_manager_user::permit, ast_manager_user::read, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_manager_user::secret, ast_manager_user::username, users, and ast_manager_user::write.

00536 {
00537    struct ast_manager_user *user = NULL;
00538 
00539    if (argc != 4)
00540       return RESULT_SHOWUSAGE;
00541 
00542    AST_LIST_LOCK(&users);
00543 
00544    if (!(user = ast_get_manager_by_name_locked(argv[3]))) {
00545       ast_cli(fd, "There is no manager called %s\n", argv[3]);
00546       AST_LIST_UNLOCK(&users);
00547       return -1;
00548    }
00549 
00550    ast_cli(fd,"\n");
00551    ast_cli(fd,
00552       "       username: %s\n"
00553       "         secret: %s\n"
00554       "           deny: %s\n"
00555       "         permit: %s\n"
00556       "           read: %s\n"
00557       "          write: %s\n"
00558       "displayconnects: %s\n",
00559       (user->username ? user->username : "(N/A)"),
00560       (user->secret ? "<Set>" : "(N/A)"),
00561       (user->deny ? user->deny : "(N/A)"),
00562       (user->permit ? user->permit : "(N/A)"),
00563       (user->read ? user->read : "(N/A)"),
00564       (user->write ? user->write : "(N/A)"),
00565       (user->displayconnects ? "yes" : "no"));
00566 
00567    AST_LIST_UNLOCK(&users);
00568 
00569    return RESULT_SUCCESS;
00570 }

static int handle_showmanagers ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 573 of file manager.c.

References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_manager_user::username, and users.

00574 {
00575    struct ast_manager_user *user = NULL;
00576    int count_amu = 0;
00577 
00578    if (argc != 3)
00579       return RESULT_SHOWUSAGE;
00580 
00581    AST_LIST_LOCK(&users);
00582 
00583    /* If there are no users, print out something along those lines */
00584    if (AST_LIST_EMPTY(&users)) {
00585       ast_cli(fd, "There are no manager users.\n");
00586       AST_LIST_UNLOCK(&users);
00587       return RESULT_SUCCESS;
00588    }
00589 
00590    ast_cli(fd, "\nusername\n--------\n");
00591 
00592    AST_LIST_TRAVERSE(&users, user, list) {
00593       ast_cli(fd, "%s\n", user->username);
00594       count_amu++;
00595    }
00596 
00597    AST_LIST_UNLOCK(&users);
00598 
00599    ast_cli(fd,"-------------------\n");
00600    ast_cli(fd,"%d manager users configured.\n", count_amu);
00601 
00602    return RESULT_SUCCESS;
00603 }

static int handle_showmancmd ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 513 of file manager.c.

References manager_action::action, ast_cli(), ast_rwlock_rdlock(), ast_rwlock_unlock(), manager_action::authority, authority_to_str(), manager_action::description, first_action, manager_action::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, and manager_action::synopsis.

00514 {
00515    struct manager_action *cur;
00516    char authority[80];
00517    int num;
00518 
00519    if (argc != 4)
00520       return RESULT_SHOWUSAGE;
00521 
00522    ast_rwlock_rdlock(&actionlock);
00523    for (cur = first_action; cur; cur = cur->next) { /* Walk the list of actions */
00524       for (num = 3; num < argc; num++) {
00525          if (!strcasecmp(cur->action, argv[num])) {
00526             ast_cli(fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", cur->action, cur->synopsis, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->description ? cur->description : "");
00527          }
00528       }
00529    }
00530    ast_rwlock_unlock(&actionlock);
00531 
00532    return RESULT_SUCCESS;
00533 }

static int handle_showmancmds ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI command Should change to "manager show commands".

Definition at line 608 of file manager.c.

References manager_action::action, ast_cli(), ast_rwlock_rdlock(), ast_rwlock_unlock(), manager_action::authority, authority_to_str(), first_action, format, manager_action::next, RESULT_SUCCESS, and manager_action::synopsis.

00609 {
00610    struct manager_action *cur;
00611    char authority[80];
00612    char *format = "  %-15.15s  %-15.15s  %-55.55s\n";
00613 
00614    ast_cli(fd, format, "Action", "Privilege", "Synopsis");
00615    ast_cli(fd, format, "------", "---------", "--------");
00616    
00617    ast_rwlock_rdlock(&actionlock);
00618    for (cur = first_action; cur; cur = cur->next) /* Walk the list of actions */
00619       ast_cli(fd, format, cur->action, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->synopsis);
00620    ast_rwlock_unlock(&actionlock);
00621    
00622    return RESULT_SUCCESS;
00623 }

static int handle_showmanconn ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI command show manager connected.

Definition at line 627 of file manager.c.

References ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, format, RESULT_SUCCESS, s, mansession::sin, and mansession::username.

00628 {
00629    struct mansession *s;
00630    char *format = "  %-15.15s  %-15.15s\n";
00631 
00632    ast_cli(fd, format, "Username", "IP Address");
00633    
00634    AST_LIST_LOCK(&sessions);
00635    AST_LIST_TRAVERSE(&sessions, s, list)
00636       ast_cli(fd, format,s->username, ast_inet_ntoa(s->sin.sin_addr));
00637    AST_LIST_UNLOCK(&sessions);
00638 
00639    return RESULT_SUCCESS;
00640 }

static int handle_showmaneventq ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI command show manager connected.

Definition at line 644 of file manager.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_UNLOCK, eventqent::category, eventqent::eventdata, eventqent::next, RESULT_SUCCESS, s, and eventqent::usecount.

00645 {
00646    struct eventqent *s;
00647 
00648    AST_LIST_LOCK(&sessions);
00649    for (s = master_eventq; s; s = s->next) {
00650       ast_cli(fd, "Usecount: %d\n",s->usecount);
00651       ast_cli(fd, "Category: %d\n", s->category);
00652       ast_cli(fd, "Event:\n%s", s->eventdata);
00653    }
00654    AST_LIST_UNLOCK(&sessions);
00655 
00656    return RESULT_SUCCESS;
00657 }

static void handle_updates ( struct mansession s,
const struct message m,
struct ast_config cfg 
) [static]

Definition at line 1153 of file manager.c.

References ast_category_append(), ast_category_delete(), ast_category_get(), ast_category_new(), ast_category_rename(), ast_strlen_zero(), ast_variable_append(), ast_variable_delete(), ast_variable_new(), ast_variable_update(), astman_get_header(), match(), ast_variable::object, ast_variable::value, and var.

Referenced by action_updateconfig().

01154 {
01155    int x;
01156    char hdr[40];
01157    const char *action, *cat, *var, *value, *match;
01158    struct ast_category *category;
01159    struct ast_variable *v;
01160    
01161    for (x=0;x<100000;x++) {
01162       unsigned int object = 0;
01163 
01164       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
01165       action = astman_get_header(m, hdr);
01166       if (ast_strlen_zero(action))
01167          break;
01168       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
01169       cat = astman_get_header(m, hdr);
01170       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
01171       var = astman_get_header(m, hdr);
01172       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
01173       value = astman_get_header(m, hdr);
01174       if (!ast_strlen_zero(value) && *value == '>') {
01175          object = 1;
01176          value++;
01177       }
01178       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
01179       match = astman_get_header(m, hdr);
01180       if (!strcasecmp(action, "newcat")) {
01181          if (!ast_strlen_zero(cat)) {
01182             category = ast_category_new(cat);
01183             if (category) {
01184                ast_category_append(cfg, category);
01185             }
01186          }
01187       } else if (!strcasecmp(action, "renamecat")) {
01188          if (!ast_strlen_zero(cat) && !ast_strlen_zero(value)) {
01189             category = ast_category_get(cfg, cat);
01190             if (category) 
01191                ast_category_rename(category, value);
01192          }
01193       } else if (!strcasecmp(action, "delcat")) {
01194          if (!ast_strlen_zero(cat))
01195             ast_category_delete(cfg, (char *) cat);
01196       } else if (!strcasecmp(action, "update")) {
01197          if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
01198             ast_variable_update(category, var, value, match, object);
01199       } else if (!strcasecmp(action, "delete")) {
01200          if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
01201             ast_variable_delete(category, (char *) var, (char *) match);
01202       } else if (!strcasecmp(action, "append")) {
01203          if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && 
01204             (category = ast_category_get(cfg, cat)) && 
01205             (v = ast_variable_new(var, value))){
01206             if (object || (match && !strcasecmp(match, "object")))
01207                v->object = 1;
01208             ast_variable_append(category, v);
01209          }
01210       }
01211    }
01212 }

static char* html_translate ( char *  in  )  [static]

Definition at line 424 of file manager.c.

References ast_build_string(), ast_malloc, len, and var.

Referenced by generic_http_callback().

00425 {
00426    int x;
00427    int colons = 0;
00428    int breaks = 0;
00429    size_t len;
00430    int count = 1;
00431    char *tmp, *var, *val, *out;
00432 
00433    for (x=0; in[x]; x++) {
00434       if (in[x] == ':')
00435          colons++;
00436       if (in[x] == '\n')
00437          breaks++;
00438    }
00439    len = strlen(in) + colons * 40 + breaks * 40; /* <tr><td></td><td></td></tr>, "<tr><td colspan=\"2\"><hr></td></tr> */
00440    out = ast_malloc(len);
00441    if (!out)
00442       return 0;
00443    tmp = out;
00444    while (*in) {
00445       var = in;
00446       while (*in && (*in >= 32))
00447          in++;
00448       if (*in) {
00449          if ((count % 4) == 0){
00450             ast_build_string(&tmp, &len, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
00451          }
00452          count = 0;
00453          while (*in && (*in < 32)) {
00454             *in = '\0';
00455             in++;
00456             count++;
00457          }
00458          val = strchr(var, ':');
00459          if (val) {
00460             *val = '\0';
00461             val++;
00462             if (*val == ' ')
00463                val++;
00464             ast_build_string(&tmp, &len, "<tr><td>%s</td><td>%s</td></tr>\r\n", var, val);
00465          }
00466       }
00467    }
00468    return out;
00469 }

int manager_event ( int  category,
const char *  event,
const char *  fmt,
  ... 
)

manager_event: Send AMI event to client

Definition at line 2515 of file manager.c.

References mansession::__lock, append_event(), ast_dynamic_str_thread_append(), ast_dynamic_str_thread_append_va, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, authority_to_str(), MANAGER_EVENT_BUF_INITSIZE, s, and mansession::waiting_thread.

Referenced by __expire_registry(), __iax2_poke_noanswer(), __login_exec(), action_agent_callback_login(), action_userevent(), add_to_queue(), agent_logoff_maintenance(), aji_log_hook(), ast_autoanswer_login(), ast_change_name(), ast_channel_alloc(), ast_channel_bridge(), ast_do_masquerade(), ast_hangup(), ast_hold_call(), ast_log(), ast_monitor_stop(), ast_set_callerid(), ast_setstate_and_cid(), autoanswer_exec(), change_hold_state(), conf_run(), do_autoanswer_thread(), expire_register(), fast_originate(), handle_init_event(), handle_response_peerpoke(), handle_response_register(), handle_statechange(), iax2_ack_registry(), join_queue(), leave_queue(), manager_log(), manager_state_cb(), notify_new_message(), park_call_full(), park_exec(), parse_register_contact(), pbx_extension_helper(), post_manager_event(), quit_handler(), realtime_exec(), record_abandoned(), register_verify(), reload_config(), reload_logger(), reload_manager(), remove_from_queue(), ring_entry(), senddialevent(), set_member_paused(), sip_poke_noanswer(), sip_reg_timeout(), socket_process(), ss_thread(), try_calling(), update_registry(), update_status(), userevent_exec(), vm_execmain(), and zt_handle_event().

02516 {
02517    struct mansession *s;
02518    char auth[80];
02519    va_list ap;
02520    struct timeval now;
02521    struct ast_dynamic_str *buf;
02522 
02523    /* Abort if there aren't any manager sessions */
02524    if (!num_sessions)
02525       return 0;
02526 
02527    if (!(buf = ast_dynamic_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE)))
02528       return -1;
02529 
02530    ast_dynamic_str_thread_set(&buf, 0, &manager_event_buf,
02531          "Event: %s\r\nPrivilege: %s\r\n",
02532           event, authority_to_str(category, auth, sizeof(auth)));
02533 
02534    if (timestampevents) {
02535       now = ast_tvnow();
02536       ast_dynamic_str_thread_append(&buf, 0, &manager_event_buf,
02537             "Timestamp: %ld.%06lu\r\n",
02538              now.tv_sec, (unsigned long) now.tv_usec);
02539    }
02540 
02541    va_start(ap, fmt);
02542    ast_dynamic_str_thread_append_va(&buf, 0, &manager_event_buf, fmt, ap);
02543    va_end(ap);
02544    
02545    ast_dynamic_str_thread_append(&buf, 0, &manager_event_buf, "\r\n");  
02546    
02547    /* Append event to master list and wake up any sleeping sessions */
02548    AST_LIST_LOCK(&sessions);
02549    append_event(buf->str, category);
02550    AST_LIST_TRAVERSE(&sessions, s, list) {
02551       ast_mutex_lock(&s->__lock);
02552       if (s->waiting_thread != AST_PTHREADT_NULL)
02553          pthread_kill(s->waiting_thread, SIGURG);
02554       ast_mutex_unlock(&s->__lock);
02555    }
02556    AST_LIST_UNLOCK(&sessions);
02557 
02558    return 0;
02559 }

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

Definition at line 2583 of file manager.c.

References ast_get_hint(), EVENT_FLAG_EXTENSIONSTATUS, and manager_event().

Referenced by init_manager().

02584 {
02585    char hint[256] = "";
02586    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
02587    /* Notify managers of change */
02588    manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
02589    return 0;
02590 }

static int process_events ( struct mansession s  )  [static]

Definition at line 2134 of file manager.c.

References mansession::__lock, ast_calloc, ast_carefulwrite(), ast_mutex_lock(), ast_mutex_unlock(), mansession::authenticated, eventqent::category, eventqent::eventdata, mansession::eventq, mansession::fd, eventqent::next, mansession::outputstr, mansession::readperm, mansession::send_events, unuse_eventqent(), and mansession::writetimeout.

Referenced by do_message(), and process_message().

02135 {
02136    struct eventqent *eqe;
02137    int ret = 0;
02138    ast_mutex_lock(&s->__lock);
02139    if (!s->eventq)
02140       s->eventq = master_eventq;
02141    while(s->eventq->next) {
02142       eqe = s->eventq->next;
02143       if ((s->authenticated && (s->readperm & eqe->category) == eqe->category) &&
02144                ((s->send_events & eqe->category) == eqe->category)) {
02145          if (s->fd > -1) {
02146             if (!ret && ast_carefulwrite(s->fd, eqe->eventdata, strlen(eqe->eventdata), s->writetimeout) < 0)
02147                ret = -1;
02148          } else if (!s->outputstr && !(s->outputstr = ast_calloc(1, sizeof(*s->outputstr)))) 
02149             ret = -1;
02150          else 
02151             ast_dynamic_str_append(&s->outputstr, 0, "%s", eqe->eventdata);
02152       }
02153       unuse_eventqent(s->eventq);
02154       s->eventq = eqe;
02155    }
02156    ast_mutex_unlock(&s->__lock);
02157    return ret;
02158 }

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

Definition at line 2185 of file manager.c.

References manager_action::action, ast_inet_ntoa(), ast_log(), ast_random(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strlen_zero(), ast_verbose(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), authenticate(), mansession::authenticated, manager_action::authority, mansession::challenge, first_action, manager_action::func, LOG_DEBUG, LOG_EVENT, manager_action::next, option_debug, option_verbose, process_events(), mansession::sessiontimeout, mansession::sin, mansession::username, VERBOSE_PREFIX_2, and mansession::writeperm.

Referenced by do_message(), and generic_http_callback().

02186 {
02187    char action[80] = "";
02188    struct manager_action *tmp;
02189    const char *id = astman_get_header(m,"ActionID");
02190    char idText[256] = "";
02191    int ret = 0;
02192 
02193    ast_copy_string(action, astman_get_header(m, "Action"), sizeof(action));
02194    if (option_debug)
02195       ast_log( LOG_DEBUG, "Manager received command '%s'\n", action );
02196 
02197    if (ast_strlen_zero(action)) {
02198       astman_send_error(s, m, "Missing action in request");
02199       return 0;
02200    }
02201    if (!ast_strlen_zero(id)) {
02202       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02203    }
02204    if (!s->authenticated) {
02205       if (!strcasecmp(action, "Challenge")) {
02206          const char *authtype = astman_get_header(m, "AuthType");
02207 
02208          if (!strcasecmp(authtype, "MD5")) {
02209             if (ast_strlen_zero(s->challenge))
02210                snprintf(s->challenge, sizeof(s->challenge), "%ld", ast_random());
02211             astman_append(s, "Response: Success\r\n"
02212                   "%s"
02213                   "Challenge: %s\r\n\r\n",
02214                   idText, s->challenge);
02215             return 0;
02216          } else {
02217             astman_send_error(s, m, "Must specify AuthType");
02218             return 0;
02219          }
02220       } else if (!strcasecmp(action, "Login")) {
02221          if (authenticate(s, m)) {
02222             sleep(1);
02223             astman_send_error(s, m, "Authentication failed");
02224             return -1;
02225          } else {
02226             s->authenticated = 1;
02227             if (option_verbose > 1) {
02228                if (displayconnects) {
02229                   ast_verbose(VERBOSE_PREFIX_2 "%sManager '%s' logged on from %s\n", 
02230                      (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
02231                }
02232             }
02233             ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", 
02234                (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
02235             astman_send_ack(s, m, "Authentication accepted");
02236          }
02237       } else if (!strcasecmp(action, "Logoff")) {
02238          astman_send_ack(s, m, "See ya");
02239          return -1;
02240       } else
02241          astman_send_error(s, m, "Authentication Required");
02242    } else {
02243       if (!strcasecmp(action, "Login"))
02244          astman_send_ack(s, m, "Already logged in");
02245       else {
02246          ast_rwlock_rdlock(&actionlock);
02247          for (tmp = first_action; tmp; tmp = tmp->next) {      
02248             if (strcasecmp(action, tmp->action))
02249                continue;
02250             if ((s->writeperm & tmp->authority) == tmp->authority) {
02251                if (tmp->func(s, m))
02252                   ret = -1;
02253             } else
02254                astman_send_error(s, m, "Permission denied");
02255             break;
02256          }
02257          ast_rwlock_unlock(&actionlock);
02258          if (!tmp)
02259             astman_send_error(s, m, "Invalid/unknown command");
02260       }
02261    }
02262    if (ret)
02263       return ret;
02264    return process_events(s);
02265 }

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

Definition at line 2351 of file manager.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), astman_append(), mansession::authenticated, destroy_session(), do_message(), LOG_EVENT, option_verbose, s, mansession::sin, mansession::username, and VERBOSE_PREFIX_2.

Referenced by accept_thread().

02352 {
02353    struct mansession *s = data;
02354    int res;
02355    
02356    astman_append(s, "Asterisk Call Manager/1.0\r\n");
02357    for (;;) {
02358       if ((res = do_message(s)) < 0)
02359          break;
02360    }
02361    if (s->authenticated) {
02362       if (option_verbose > 1) {
02363          if (displayconnects) 
02364             ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02365       }
02366       ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02367    } else {
02368       if (option_verbose > 1) {
02369          if (displayconnects)
02370             ast_verbose(VERBOSE_PREFIX_2 "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
02371       }
02372       ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
02373    }
02374 
02375    /* It is possible under certain circumstances for this session thread
02376       to complete its work and exit *before* the thread that created it
02377       has finished executing the ast_pthread_create_background() function.
02378       If this occurs, some versions of glibc appear to act in a buggy
02379       fashion and attempt to write data into memory that it thinks belongs
02380       to the thread but is in fact not owned by the thread (or may have
02381       been freed completely).
02382 
02383       Causing this thread to yield to other threads at least one time
02384       appears to work around this bug.
02385    */
02386    usleep(1);
02387 
02388    destroy_session(s);
02389    return NULL;
02390 }

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

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

Referenced by action_events(), and authenticate().

00942 {
00943    int maskint = strings_to_mask(eventmask);
00944 
00945    ast_mutex_lock(&s->__lock);
00946    if (maskint >= 0) 
00947       s->send_events = maskint;
00948    ast_mutex_unlock(&s->__lock);
00949    
00950    return maskint;
00951 }

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

Definition at line 910 of file manager.c.

References ast_false(), ast_instring(), ast_is_number(), ast_strlen_zero(), ast_true(), and perms.

Referenced by set_eventmask().

00911 {
00912    int x, ret = -1;
00913    
00914    x = ast_is_number(string);
00915 
00916    if (x)
00917       ret = x;
00918    else if (ast_strlen_zero(string))
00919       ret = -1;
00920    else if (ast_false(string))
00921       ret = 0;
00922    else if (ast_true(string)) {
00923       ret = 0;
00924       for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++)
00925          ret |= perms[x].num;    
00926    } else {
00927       ret = 0;
00928       for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++) {
00929          if (ast_instring(string, perms[x].label, ',')) 
00930             ret |= perms[x].num;    
00931       }
00932    }
00933 
00934    return ret;
00935 }

static void unuse_eventqent ( struct eventqent e  )  [static]

Definition at line 732 of file manager.c.

References eventqent::next, and eventqent::usecount.

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

00733 {
00734    if (ast_atomic_dec_and_test(&e->usecount) && e->next)
00735       pthread_kill(t, SIGURG);
00736 }

static int variable_count_cmp_fn ( void *  obj,
void *  vstr,
int  flags 
) [static]

Definition at line 314 of file manager.c.

References variable_count::varname.

Referenced by xml_translate().

00315 {
00316    /* Due to the simplicity of struct variable_count, it makes no difference
00317     * if you pass in objects or strings, the same operation applies. This is
00318     * due to the fact that the hash occurs on the first element, which means
00319     * the address of both the struct and the string are exactly the same. */
00320    struct variable_count *vc = obj;
00321    char *str = vstr;
00322    return !strcmp(vc->varname, str) ? CMP_MATCH : 0;
00323 }

static int variable_count_hash_fn ( const void *  vvc,
const int  flags 
) [static]

Definition at line 302 of file manager.c.

References compress_char(), and variable_count::varname.

Referenced by xml_translate().

00303 {
00304    const struct variable_count *vc = vvc;
00305    int res = 0, i;
00306    for (i = 0; i < 5; i++) {
00307       if (vc->varname[i] == '\0')
00308          break;
00309       res += compress_char(vc->varname[i]) << (i * 6);
00310    }
00311    return res;
00312 }

static void xml_copy_escape ( char **  dst,
size_t *  maxlen,
const char *  src,
int  lower 
) [static]

Definition at line 247 of file manager.c.

Referenced by xml_translate().

00248 {
00249    while (*src && (*maxlen > 6)) {
00250       switch (*src) {
00251       case '<':
00252          strcpy(*dst, "&lt;");
00253          (*dst) += 4;
00254          *maxlen -= 4;
00255          break;
00256       case '>':
00257          strcpy(*dst, "&gt;");
00258          (*dst) += 4;
00259          *maxlen -= 4;
00260          break;
00261       case '\"':
00262          strcpy(*dst, "&quot;");
00263          (*dst) += 6;
00264          *maxlen -= 6;
00265          break;
00266       case '\'':
00267          strcpy(*dst, "&apos;");
00268          (*dst) += 6;
00269          *maxlen -= 6;
00270          break;
00271       case '&':
00272          strcpy(*dst, "&amp;");
00273          (*dst) += 5;
00274          *maxlen -= 5;
00275          break;      
00276       default:
00277          *(*dst)++ = lower ? tolower(*src) : *src;
00278          (*maxlen)--;
00279       }
00280       src++;
00281    }
00282 }

static char* xml_translate ( char *  in,
struct ast_variable vars 
) [static]

Definition at line 325 of file manager.c.

References ao2_alloc(), ao2_container_alloc(), ao2_find(), ao2_ref(), ast_build_string(), ast_malloc, variable_count::count, len, ast_variable::name, ast_variable::next, ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().

Referenced by generic_http_callback().

00326 {
00327    struct ast_variable *v;
00328    char *dest = NULL;
00329    char *out, *tmp, *var, *val;
00330    char *objtype = NULL;
00331    int colons = 0;
00332    int breaks = 0;
00333    size_t len;
00334    int count = 1;
00335    int escaped = 0;
00336    int inobj = 0;
00337    int x;
00338    struct variable_count *vc = NULL;
00339    struct ao2_container *vco = NULL;
00340 
00341    for (v = vars; v; v = v->next) {
00342       if (!dest && !strcasecmp(v->name, "ajaxdest"))
00343          dest = v->value;
00344       else if (!objtype && !strcasecmp(v->name, "ajaxobjtype")) 
00345          objtype = v->value;
00346    }
00347    if (!dest)
00348       dest = "unknown";
00349    if (!objtype)
00350       objtype = "generic";
00351    for (x = 0; in[x]; x++) {
00352       if (in[x] == ':')
00353          colons++;
00354       else if (in[x] == '\n')
00355          breaks++;
00356       else if (strchr("&\"<>\'", in[x]))
00357          escaped++;
00358    }
00359    len = (size_t) (strlen(in) + colons * 5 + breaks * (40 + strlen(dest) + strlen(objtype)) + escaped * 10); /* foo="bar", "<response type=\"object\" id=\"dest\"", "&amp;" */
00360    out = ast_malloc(len);
00361    if (!out)
00362       return 0;
00363    tmp = out;
00364    while (*in) {
00365       var = in;
00366       while (*in && (*in >= 32))
00367          in++;
00368       if (*in) {
00369          if ((count > 3) && inobj) {
00370             ast_build_string(&tmp, &len, " /></response>\n");
00371             inobj = 0;
00372 
00373             /* Entity is closed, so close out the name cache */
00374             ao2_ref(vco, -1);
00375             vco = NULL;
00376          }
00377          count = 0;
00378          while (*in && (*in < 32)) {
00379             *in = '\0';
00380             in++;
00381             count++;
00382          }
00383          val = strchr(var, ':');
00384          if (val) {
00385             *val = '\0';
00386             val++;
00387             if (*val == ' ')
00388                val++;
00389             if (!inobj) {
00390                vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
00391                ast_build_string(&tmp, &len, "<response type='object' id='%s'><%s", dest, objtype);
00392                inobj = 1;
00393             }
00394 
00395             /* Check if the var has been used already */
00396             if ((vc = ao2_find(vco, var, 0)))
00397                vc->count++;
00398             else {
00399                /* Create a new entry for this one */
00400                vc = ao2_alloc(sizeof(*vc), NULL);
00401                vc->varname = var;
00402                vc->count = 1;
00403                ao2_link(vco, vc);
00404             }
00405 
00406             ast_build_string(&tmp, &len, " ");
00407             xml_copy_escape(&tmp, &len, var, 1);
00408             if (vc->count > 1)
00409                ast_build_string(&tmp, &len, "-%d", vc->count);
00410             ast_build_string(&tmp, &len, "='");
00411             xml_copy_escape(&tmp, &len, val, 0);
00412             ast_build_string(&tmp, &len, "'");
00413             ao2_ref(vc, -1);
00414          }
00415       }
00416    }
00417    if (inobj)
00418       ast_build_string(&tmp, &len, " /></response>\n");
00419    if (vco)
00420       ao2_ref(vco, -1);
00421    return out;
00422 }


Variable Documentation

int asock = -1 [static]

Definition at line 104 of file manager.c.

int block_sockets [static]

Definition at line 110 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 706 of file manager.c.

Initial value:

 {
   { "show", "manager", "command", NULL },
   handle_showmancmd, NULL,
   NULL, complete_show_mancmd }

Definition at line 686 of file manager.c.

Initial value:

 {
   { "show", "manager", "commands", NULL },
   handle_showmancmds, NULL,
   NULL }

Definition at line 691 of file manager.c.

Initial value:

 {
   { "show", "manager", "connected", NULL },
   handle_showmanconn, NULL,
   NULL }

Definition at line 696 of file manager.c.

Initial value:

 {
   { "show", "manager", "eventq", NULL },
   handle_showmaneventq, NULL,
   NULL }

Definition at line 701 of file manager.c.

const char* command_blacklist[] [static]

Initial value:

 {
   "module load",
   "module unload",
}

Definition at line 139 of file manager.c.

int displayconnects = 1 [static]

Definition at line 105 of file manager.c.

int enabled [static]

Definition at line 102 of file manager.c.

struct manager_action* first_action [static]

int httptimeout = 60 [static]

Definition at line 107 of file manager.c.

char mandescr_command[] [static]

Initial value:

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

Definition at line 1751 of file manager.c.

char mandescr_events[] [static]

Definition at line 1379 of file manager.c.

char mandescr_extensionstate[] [static]

Definition at line 2062 of file manager.c.

char mandescr_getconfig[] [static]

Initial value:

"Description: A 'GetConfig' action will dump the contents of a configuration\n"
"file by category and contents.\n"
"Variables:\n"
"   Filename: Configuration filename (e.g. foo.conf)\n"

Definition at line 1110 of file manager.c.

char mandescr_getvar[] [static]

Definition at line 1524 of file manager.c.

char mandescr_hangup[] [static]

Initial value:

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

Definition at line 1411 of file manager.c.

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

char mandescr_logoff[] [static]

Initial value:

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

Definition at line 1401 of file manager.c.

char mandescr_mailboxcount[] [static]

Definition at line 2026 of file manager.c.

char mandescr_mailboxstatus[] [static]

Help text for manager command mailboxstatus.

Definition at line 1994 of file manager.c.

char mandescr_message[] [static]

Definition at line 1444 of file manager.c.

char mandescr_originate[] [static]

Definition at line 1851 of file manager.c.

char mandescr_ping[] [static]

Initial value:

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

Definition at line 1099 of file manager.c.

char mandescr_redirect[] [static]

Definition at line 1666 of file manager.c.

char mandescr_setvar[] [static]

Definition at line 1487 of file manager.c.

char mandescr_timeout[] [static]

Definition at line 2103 of file manager.c.

char mandescr_updateconfig[] [static]

Definition at line 1214 of file manager.c.

char mandescr_userevent[] [static]

Definition at line 2160 of file manager.c.

char mandescr_waitevent[] [static]

Manager WAITEVENT.

Definition at line 1265 of file manager.c.

struct eventqent* master_eventq = NULL

Definition at line 114 of file manager.c.

int num_sessions [static]

Definition at line 111 of file manager.c.

struct permalias perms[] [static]

int portno = DEFAULT_MANAGER_PORT [static]

Definition at line 103 of file manager.c.

Referenced by ast_netsock_bind(), create_addr(), process_sdp(), and set_config().

char showmanager_help[] [static]

Initial value:

" Usage: manager show user <user>\n"
"        Display all information related to the manager user specified.\n"

Definition at line 682 of file manager.c.

char showmanagers_help[] [static]

Initial value:

"Usage: manager show users\n"
"       Prints a listing of all managers that are currently configured on that\n"
" system.\n"

Definition at line 677 of file manager.c.

char showmancmd_help[] [static]

Initial value:

 
"Usage: manager show command <actionname>\n"
"  Shows the detailed description for a specific Asterisk manager interface command.\n"

Definition at line 659 of file manager.c.

char showmancmds_help[] [static]

Initial value:

 
"Usage: manager show commands\n"
"  Prints a listing of all the available Asterisk manager interface commands.\n"

Definition at line 663 of file manager.c.

char showmanconn_help[] [static]

Initial value:

 
"Usage: manager show connected\n"
"  Prints a listing of the users that are currently connected to the\n"
"Asterisk manager interface.\n"

Definition at line 667 of file manager.c.

char showmaneventq_help[] [static]

Initial value:

 
"Usage: manager show eventq\n"
"  Prints a listing of all events pending in the Asterisk manger\n"
"event queue.\n"

Definition at line 672 of file manager.c.

pthread_t t [static]

Definition at line 109 of file manager.c.

Referenced by __schedule_action(), acf_odbc_write(), add_sdp(), add_t38_sdp(), append_date(), ast_channel_bridge(), ast_check_timing(), ast_do_masquerade(), ast_get_time_t(), ast_httpd_helper_thread(), ast_log(), ast_pbx_start(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_de(), ast_translator_build_path(), ast_verbose(), background_detect_exec(), build_mapping(), byteReverse(), callerid_genmsg(), callerid_getcarrier(), cb_events(), cdr_get_tv(), check_switch_expr(), check_user_full(), cli_prompt(), config_text_file_save(), destroy(), do_monitor(), does_peer_need_mwi(), dump_cmd_queues(), expr2_token_subst(), gen_match_to_pattern(), gen_tone(), gen_tones(), get_date(), get_trans_id(), handle_bchan(), handle_enbloc_call_message(), handle_hd_hf(), handle_offhook_message(), handle_save_dialplan(), handle_soft_key_event_message(), handle_stimulus_message(), iax2_datetime(), iax2_process_thread(), iax2_show_threads(), iax_template_parse(), launch_service(), listener(), local_new(), localsub(), lws2sws(), manager_log(), MD5Update(), misdn_read(), osp_create_provider(), osp_load(), packdate(), parse_moved_contact(), pgsql_log(), play_message_datetime(), prune_gateways(), rebuild_matrix(), register_verify(), send_request(), SHA1ProcessMessageBlock(), socket_read(), sqlite_log(), strip_quotes(), tdd_getcarrier(), time1(), time2(), time2sub(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_state_notify(), vmu_tm(), and write_metadata().

int timestampevents [static]

Definition at line 106 of file manager.c.


Generated on Sat Apr 12 07:12:57 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5