Wed Aug 20 06:29:37 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
#define MAX_BLACKLIST_CMD_LEN   2

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_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)
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 int check_blacklist (const char *cmd)
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)
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
struct {
   char *   words [AST_MAX_CMD_LEN]
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_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.
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 116 of file manager.c.

Referenced by astman_append().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 113 of file manager.c.

Referenced by manager_event().

#define MAX_BLACKLIST_CMD_LEN   2

Definition at line 134 of file manager.c.

Referenced by check_blacklist().


Function Documentation

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

Definition at line 2360 of file manager.c.

References asock, 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(), block_sockets, destroy_session(), displayconnects, errno, pollfd::events, pollfd::fd, ast_channel::flags, free, free_session(), LOG_WARNING, master_eventq, eventqent::next, num_sessions, option_verbose, poll(), POLLIN, s, session_do(), sessions, eventqent::usecount, and VERBOSE_PREFIX_2.

Referenced by reload_config().

02361 {
02362    int as;
02363    struct sockaddr_in sin;
02364    socklen_t sinlen;
02365    struct eventqent *eqe;
02366    struct mansession *s;
02367    struct protoent *p;
02368    int arg = 1;
02369    int flags;
02370    pthread_attr_t attr;
02371    time_t now;
02372    struct pollfd pfds[1];
02373 
02374    pthread_attr_init(&attr);
02375    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02376 
02377    for (;;) {
02378       time(&now);
02379       AST_LIST_LOCK(&sessions);
02380       AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
02381          if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
02382             AST_LIST_REMOVE_CURRENT(&sessions, list);
02383             num_sessions--;
02384             if (s->authenticated && (option_verbose > 1) && displayconnects) {
02385                ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' timed out from %s\n",
02386                   s->username, ast_inet_ntoa(s->sin.sin_addr));
02387             }
02388             free_session(s);
02389             break;   
02390          }
02391       }
02392       AST_LIST_TRAVERSE_SAFE_END
02393       /* Purge master event queue of old, unused events, but make sure we
02394          always keep at least one in the queue */
02395       eqe = master_eventq;
02396       while (master_eventq->next && !master_eventq->usecount) {
02397          eqe = master_eventq;
02398          master_eventq = master_eventq->next;
02399          free(eqe);
02400       }
02401       AST_LIST_UNLOCK(&sessions);
02402 
02403       sinlen = sizeof(sin);
02404       pfds[0].fd = asock;
02405       pfds[0].events = POLLIN;
02406       /* Wait for something to happen, but timeout every few seconds so
02407          we can ditch any old manager sessions */
02408       if (poll(pfds, 1, 5000) < 1)
02409          continue;
02410       as = accept(asock, (struct sockaddr *)&sin, &sinlen);
02411       if (as < 0) {
02412          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
02413          continue;
02414       }
02415       p = getprotobyname("tcp");
02416       if (p) {
02417          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
02418             ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
02419          }
02420       }
02421       if (!(s = ast_calloc(1, sizeof(*s))))
02422          continue;
02423 
02424       memcpy(&s->sin, &sin, sizeof(sin));
02425       s->writetimeout = 100;
02426       s->waiting_thread = AST_PTHREADT_NULL;
02427 
02428       if (!block_sockets) {
02429          /* For safety, make sure socket is non-blocking */
02430          flags = fcntl(as, F_GETFL);
02431          fcntl(as, F_SETFL, flags | O_NONBLOCK);
02432       } else {
02433          flags = fcntl(as, F_GETFL);
02434          fcntl(as, F_SETFL, flags & ~O_NONBLOCK);
02435       }
02436       ast_mutex_init(&s->__lock);
02437       s->fd = as;
02438       s->send_events = -1;
02439       AST_LIST_LOCK(&sessions);
02440       AST_LIST_INSERT_HEAD(&sessions, s, list);
02441       num_sessions++;
02442       /* Find the last place in the master event queue and hook ourselves
02443          in there */
02444       s->eventq = master_eventq;
02445       while(s->eventq->next)
02446          s->eventq = s->eventq->next;
02447       ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
02448       AST_LIST_UNLOCK(&sessions);
02449       if (ast_pthread_create_background(&s->t, &attr, session_do, s))
02450          destroy_session(s);
02451    }
02452    pthread_attr_destroy(&attr);
02453    return NULL;
02454 }

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

action_command: Manager command "command" - execute CLI command

Definition at line 1730 of file manager.c.

References ast_calloc, ast_cli_command(), ast_free, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), s, S_OR, and term_strip().

Referenced by init_manager().

01731 {
01732    const char *cmd = astman_get_header(m, "Command");
01733    const char *id = astman_get_header(m, "ActionID");
01734    char *buf, *final_buf;
01735    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
01736    int fd = mkstemp(template);
01737    off_t l;
01738 
01739    if (ast_strlen_zero(cmd)) {
01740       astman_send_error(s, m, "No command provided");
01741       return 0;
01742    }
01743 
01744    if (check_blacklist(cmd)) {
01745       astman_send_error(s, m, "Command blacklisted");
01746       return 0;
01747    }
01748 
01749    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
01750    if (!ast_strlen_zero(id))
01751       astman_append(s, "ActionID: %s\r\n", id);
01752    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
01753    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
01754    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
01755 
01756    /* This has a potential to overflow the stack.  Hence, use the heap. */
01757    buf = ast_calloc(1, l + 1);
01758    final_buf = ast_calloc(1, l + 1);
01759    if (buf) {
01760       lseek(fd, 0, SEEK_SET);
01761       read(fd, buf, l);
01762       buf[l] = '\0';
01763       if (final_buf) {
01764          term_strip(final_buf, buf, l);
01765          final_buf[l] = '\0';
01766       }
01767       astman_append(s, "%s", S_OR(final_buf, buf));
01768       ast_free(buf);
01769    }
01770    close(fd);
01771    unlink(template);
01772    astman_append(s, "--END COMMAND--\r\n\r\n");
01773    if (final_buf)
01774       ast_free(final_buf);
01775    return 0;
01776 }

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

Definition at line 1386 of file manager.c.

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

Referenced by init_manager().

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

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

Definition at line 2036 of file manager.c.

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

Referenced by init_manager().

02037 {
02038    const char *exten = astman_get_header(m, "Exten");
02039    const char *context = astman_get_header(m, "Context");
02040    const char *id = astman_get_header(m,"ActionID");
02041    char idText[256] = "";
02042    char hint[256] = "";
02043    int status;
02044    if (ast_strlen_zero(exten)) {
02045       astman_send_error(s, m, "Extension not specified");
02046       return 0;
02047    }
02048    if (ast_strlen_zero(context))
02049       context = "default";
02050    status = ast_extension_state(NULL, context, exten);
02051    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
02052         if (!ast_strlen_zero(id)) {
02053                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02054         }
02055    astman_append(s, "Response: Success\r\n"
02056                     "%s"
02057                "Message: Extension Status\r\n"
02058                "Exten: %s\r\n"
02059                "Context: %s\r\n"
02060                "Hint: %s\r\n"
02061                "Status: %d\r\n\r\n",
02062                idText,exten, context, hint, status);
02063    return 0;
02064 }

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

Definition at line 1115 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, s, and ast_variable::value.

Referenced by init_manager().

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

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

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

Referenced by init_manager().

01479 {
01480    struct ast_channel *c = NULL;
01481    const char *name = astman_get_header(m, "Channel");
01482    const char *varname = astman_get_header(m, "Variable");
01483    const char *id = astman_get_header(m,"ActionID");
01484    char *varval;
01485    char workspace[1024] = "";
01486 
01487    if (ast_strlen_zero(varname)) {
01488       astman_send_error(s, m, "No variable specified");
01489       return 0;
01490    }
01491 
01492    if (!ast_strlen_zero(name)) {
01493       c = ast_get_channel_by_name_locked(name);
01494       if (!c) {
01495          astman_send_error(s, m, "No such channel");
01496          return 0;
01497       }
01498    }
01499 
01500    if (varname[strlen(varname) - 1] == ')') {
01501       char *copy = ast_strdupa(varname);
01502 
01503       ast_func_read(c, copy, workspace, sizeof(workspace));
01504       varval = workspace;
01505    } else {
01506       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
01507    }
01508 
01509    if (c)
01510       ast_channel_unlock(c);
01511    astman_append(s, "Response: Success\r\n"
01512       "Variable: %s\r\nValue: %s\r\n", varname, varval);
01513    if (!ast_strlen_zero(id))
01514       astman_append(s, "ActionID: %s\r\n",id);
01515    astman_append(s, "\r\n");
01516 
01517    return 0;
01518 }

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

Definition at line 1415 of file manager.c.

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

Referenced by init_manager().

01416 {
01417    struct ast_channel *c = NULL;
01418    const char *name = astman_get_header(m, "Channel");
01419    if (ast_strlen_zero(name)) {
01420       astman_send_error(s, m, "No channel specified");
01421       return 0;
01422    }
01423    c = ast_get_channel_by_name_locked(name);
01424    if (!c) {
01425       astman_send_error(s, m, "No such channel");
01426       return 0;
01427    }
01428    ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
01429    ast_channel_unlock(c);
01430    astman_send_ack(s, m, "Channel Hungup");
01431    return 0;
01432 }

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 1359 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, s, and manager_action::synopsis.

Referenced by init_manager().

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

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

Definition at line 1404 of file manager.c.

References astman_send_response(), and s.

Referenced by init_manager().

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

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

Definition at line 2000 of file manager.c.

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

Referenced by init_manager().

02001 {
02002    const char *mailbox = astman_get_header(m, "Mailbox");
02003    const char *id = astman_get_header(m,"ActionID");
02004    char idText[256] = "";
02005    int newmsgs = 0, oldmsgs = 0;
02006    if (ast_strlen_zero(mailbox)) {
02007       astman_send_error(s, m, "Mailbox not specified");
02008       return 0;
02009    }
02010    ast_app_inboxcount(mailbox, &newmsgs, &oldmsgs);
02011    if (!ast_strlen_zero(id)) {
02012       snprintf(idText, sizeof(idText), "ActionID: %s\r\n",id);
02013    }
02014    astman_append(s, "Response: Success\r\n"
02015                "%s"
02016                "Message: Mailbox Message Count\r\n"
02017                "Mailbox: %s\r\n"
02018                "NewMessages: %d\r\n"
02019                "OldMessages: %d\r\n" 
02020                "\r\n",
02021                 idText,mailbox, newmsgs, oldmsgs);
02022    return 0;
02023 }

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

Definition at line 1968 of file manager.c.

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

Referenced by init_manager().

01969 {
01970    const char *mailbox = astman_get_header(m, "Mailbox");
01971    const char *id = astman_get_header(m,"ActionID");
01972    char idText[256] = "";
01973    int ret;
01974    if (ast_strlen_zero(mailbox)) {
01975       astman_send_error(s, m, "Mailbox not specified");
01976       return 0;
01977    }
01978         if (!ast_strlen_zero(id))
01979                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
01980    ret = ast_app_has_voicemail(mailbox, NULL);
01981    astman_append(s, "Response: Success\r\n"
01982                "%s"
01983                "Message: Mailbox Status\r\n"
01984                "Mailbox: %s\r\n"
01985                "Waiting: %d\r\n\r\n", idText, mailbox, ret);
01986    return 0;
01987 }

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

Definition at line 1842 of file manager.c.

References app, ast_callerid_parse(), ast_calloc, ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create, ast_shrink_phone_number(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), context, ast_channel::data, exten, fast_originate(), format, name, ast_channel::priority, s, and ast_channel::tech.

Referenced by init_manager().

01843 {
01844    const char *name = astman_get_header(m, "Channel");
01845    const char *exten = astman_get_header(m, "Exten");
01846    const char *context = astman_get_header(m, "Context");
01847    const char *priority = astman_get_header(m, "Priority");
01848    const char *timeout = astman_get_header(m, "Timeout");
01849    const char *callerid = astman_get_header(m, "CallerID");
01850    const char *account = astman_get_header(m, "Account");
01851    const char *app = astman_get_header(m, "Application");
01852    const char *appdata = astman_get_header(m, "Data");
01853    const char *async = astman_get_header(m, "Async");
01854    const char *id = astman_get_header(m, "ActionID");
01855    const char *codecs = astman_get_header(m, "Codecs");
01856    struct ast_variable *vars = astman_get_variables(m);
01857    char *tech, *data;
01858    char *l = NULL, *n = NULL;
01859    int pi = 0;
01860    int res;
01861    int to = 30000;
01862    int reason = 0;
01863    char tmp[256];
01864    char tmp2[256];
01865    int format = AST_FORMAT_SLINEAR;
01866    
01867    pthread_t th;
01868    pthread_attr_t attr;
01869    if (!name) {
01870       astman_send_error(s, m, "Channel not specified");
01871       return 0;
01872    }
01873    if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
01874       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
01875          astman_send_error(s, m, "Invalid priority");
01876          return 0;
01877       }
01878    }
01879    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%d", &to) != 1)) {
01880       astman_send_error(s, m, "Invalid timeout");
01881       return 0;
01882    }
01883    ast_copy_string(tmp, name, sizeof(tmp));
01884    tech = tmp;
01885    data = strchr(tmp, '/');
01886    if (!data) {
01887       astman_send_error(s, m, "Invalid channel");
01888       return 0;
01889    }
01890    *data++ = '\0';
01891    ast_copy_string(tmp2, callerid, sizeof(tmp2));
01892    ast_callerid_parse(tmp2, &n, &l);
01893    if (n) {
01894       if (ast_strlen_zero(n))
01895          n = NULL;
01896    }
01897    if (l) {
01898       ast_shrink_phone_number(l);
01899       if (ast_strlen_zero(l))
01900          l = NULL;
01901    }
01902    if (!ast_strlen_zero(codecs)) {
01903       format = 0;
01904       ast_parse_allow_disallow(NULL, &format, codecs, 1);
01905    }
01906    if (ast_true(async)) {
01907       struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
01908       if (!fast) {
01909          res = -1;
01910       } else {
01911          if (!ast_strlen_zero(id))
01912             snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s\r\n", id);
01913          ast_copy_string(fast->tech, tech, sizeof(fast->tech));
01914             ast_copy_string(fast->data, data, sizeof(fast->data));
01915          ast_copy_string(fast->app, app, sizeof(fast->app));
01916          ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
01917          if (l)
01918             ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
01919          if (n)
01920             ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
01921          fast->vars = vars;   
01922          ast_copy_string(fast->context, context, sizeof(fast->context));
01923          ast_copy_string(fast->exten, exten, sizeof(fast->exten));
01924          ast_copy_string(fast->account, account, sizeof(fast->account));
01925          fast->format = format;
01926          fast->timeout = to;
01927          fast->priority = pi;
01928          pthread_attr_init(&attr);
01929          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01930          if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
01931             ast_free(fast);
01932             res = -1;
01933          } else {
01934             res = 0;
01935          }
01936          pthread_attr_destroy(&attr);
01937       }
01938    } else if (!ast_strlen_zero(app)) {
01939          res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
01940       } else {
01941       if (exten && context && pi)
01942             res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
01943       else {
01944          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
01945          return 0;
01946       }
01947    }   
01948    if (!res)
01949       astman_send_ack(s, m, "Originate successfully queued");
01950    else
01951       astman_send_error<