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_user * | ast_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_variable * | astman_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_action * | first_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 eventqent * | master_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 |
#define ASTMAN_APPEND_BUF_INITSIZE 256 |
#define MANAGER_EVENT_BUF_INITSIZE 256 |
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] |
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
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
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 | |||
) |
Definition at line 850 of file manager.c.
References astman_send_response().
Referenced by action_agent_callback_login(), action_agent_logoff(), action_agents(), action_hangup(), action_message(), action_redirect(), action_setcdruserfield(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_zapdialoffhook(), action_zapdndoff(), action_zapdndon(), action_zaprestart(), action_zapshowchannels(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbget(), manager_dbput(), 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_peers(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().
00851 { 00852 astman_send_response(s, m, "Success", msg); 00853 }
void astman_send_error | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | error | |||
) |
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, "<"); 00253 (*dst) += 4; 00254 *maxlen -= 4; 00255 break; 00256 case '>': 00257 strcpy(*dst, ">"); 00258 (*dst) += 4; 00259 *maxlen -= 4; 00260 break; 00261 case '\"': 00262 strcpy(*dst, """); 00263 (*dst) += 6; 00264 *maxlen -= 6; 00265 break; 00266 case '\'': 00267 strcpy(*dst, "'"); 00268 (*dst) += 6; 00269 *maxlen -= 6; 00270 break; 00271 case '&': 00272 strcpy(*dst, "&"); 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\"", "&" */ 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 }
int block_sockets [static] |
struct ast_cli_entry cli_manager[] [static] |
struct ast_cli_entry cli_show_manager_command_deprecated [static] |
Initial value:
{ { "show", "manager", "command", NULL }, handle_showmancmd, NULL, NULL, complete_show_mancmd }
struct ast_cli_entry cli_show_manager_commands_deprecated [static] |
Initial value:
{ { "show", "manager", "commands", NULL }, handle_showmancmds, NULL, NULL }
struct ast_cli_entry cli_show_manager_connected_deprecated [static] |
Initial value:
{ { "show", "manager", "connected", NULL }, handle_showmanconn, NULL, NULL }
struct ast_cli_entry cli_show_manager_eventq_deprecated [static] |
Initial value:
{ { "show", "manager", "eventq", NULL }, handle_showmaneventq, NULL, NULL }
const char* command_blacklist[] [static] |
int displayconnects = 1 [static] |
struct manager_action* first_action [static] |
Definition at line 203 of file manager.c.
Referenced by action_listcommands(), ast_manager_register_struct(), ast_manager_unregister(), complete_show_mancmd(), handle_showmancmd(), handle_showmancmds(), and process_message().
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[] [static] |
char mandescr_message[] [static] |
char mandescr_originate[] [static] |
char mandescr_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[] [static] |
struct eventqent* master_eventq = NULL |
int num_sessions [static] |
Referenced by authority_to_str(), get_perm(), and strings_to_mask().
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] |
char showmanagers_help[] [static] |
char showmancmd_help[] [static] |
char showmancmds_help[] [static] |
char showmanconn_help[] [static] |
char showmaneventq_help[] [static] |
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] |