![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
manager.c File Reference
Definition in file manager.c.
#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/http.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
Include dependency graph for manager.c:

Go to the source code of this file.
Data Structures | |
| struct | ast_manager_user |
| user descriptor, as read from the config file. More... | |
| struct | eventqent |
| struct | fast_originate_helper |
| struct | mansession |
| struct | permalias |
Defines | |
| #define | ASTMAN_APPEND_BUF_INITSIZE 256 |
| #define | MANAGER_EVENT_BUF_INITSIZE 256 |
| #define | MSG_MOREDATA ((char *)astman_send_response) |
| send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
| #define | NEW_EVENT(m) (AST_LIST_NEXT(m->last_ev, eq_next)) |
| #define | ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" |
| #define | TEST_STRING "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>" |
Enumerations | |
| enum | output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML } |
Functions | |
| int | __manager_event (int category, const char *event, const char *file, int line, const char *func, const char *fmt,...) |
| manager_event: Send AMI event to client | |
| static int | action_challenge (struct mansession *s, const struct message *m) |
| static int | action_command (struct mansession *s, const struct message *m) |
| Manager command "command" - execute CLI command. | |
| static int | action_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_login (struct mansession *s, const struct message *m) |
| static int | action_logoff (struct mansession *s, const struct message *m) |
| static int | action_mailboxcount (struct mansession *s, const struct message *m) |
| static int | action_mailboxstatus (struct mansession *s, const struct message *m) |
| static int | action_originate (struct mansession *s, const struct message *m) |
| static int | action_ping (struct mansession *s, const struct message *m) |
| static int | action_redirect (struct mansession *s, const struct message *m) |
| action_redirect: The redirect manager command | |
| static int | action_sendtext (struct mansession *s, const struct message *m) |
| static int | action_setvar (struct mansession *s, const struct message *m) |
| static int | action_status (struct mansession *s, const struct message *m) |
| Manager "status" command to show channels. | |
| static int | action_timeout (struct mansession *s, const struct message *m) |
| static int | action_updateconfig (struct mansession *s, const struct message *m) |
| static int | action_userevent (struct mansession *s, const struct message *m) |
| static int | action_waitevent (struct mansession *s, const struct message *m) |
| static int | append_event (const char *str, int category) |
| static int | ast_instring (const char *bigstr, const char *smallstr, const char delim) |
| static | AST_LIST_HEAD_STATIC (users, ast_manager_user) |
| list of users found in the config file | |
| static | AST_LIST_HEAD_STATIC (sessions, mansession) |
| static | AST_LIST_HEAD_STATIC (all_events, eventqent) |
| int | ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description) |
| register a new command with manager, including online help. This is the preferred way to register a manager command | |
| void | ast_manager_register_hook (struct manager_custom_hook *hook) |
| Add a custom hook to be called when an event is fired. | |
| static int | ast_manager_register_struct (struct manager_action *act) |
| int | ast_manager_unregister (char *action) |
| void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
| Delete a custom hook to be called when an event is fired. | |
| static | AST_RWLIST_HEAD_STATIC (manager_hooks, manager_custom_hook) |
| AST_RWLOCK_DEFINE_STATIC (actionlock) | |
| AST_THREADSTORAGE (manager_event_buf) | |
| AST_THREADSTORAGE (astman_append_buf) | |
| void | astman_append (struct mansession *s, const char *fmt,...) |
| const char * | astman_get_header (const struct message *m, char *var) |
| 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_listack (struct mansession *s, const struct message *m, char *msg, char *listflag) |
| void | astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg) |
| static void | astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag) |
| static void | astman_start_ack (struct mansession *s, const struct message *m) |
| static int | authenticate (struct mansession *s, const struct message *m) |
| static char * | authority_to_str (int authority, struct ast_str **res) |
| Convert authority code to a list of options. | |
| static char * | complete_show_mancmd (const char *line, const char *word, int pos, int state) |
| static void | destroy_session (struct mansession *s) |
| static int | do_message (struct mansession *s) |
| static void * | fast_originate (void *data) |
| static struct mansession * | find_session (unsigned long ident) |
| static void | free_session (struct mansession *s) |
| static struct ast_str * | generic_http_callback (enum output_format format, struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
| static int | get_input (struct mansession *s, char *output) |
| static struct ast_manager_user * | get_manager_by_name_locked (const char *name) |
| static int | get_perm (const char *instr) |
| static struct eventqent * | grab_last (void) |
| Event list management functions. We assume that the event list always has at least one element, and the delete code will not remove the last entry even if the. | |
| static int | handle_mandebug (int fd, int argc, char *argv[]) |
| 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 manager list commands. | |
| static int | handle_showmanconn (int fd, int argc, char *argv[]) |
| CLI command manager list connected. | |
| static int | handle_showmaneventq (int fd, int argc, char *argv[]) |
| CLI command manager list eventq. | |
| static void | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg) |
| int | init_manager (void) |
| static struct ast_str * | manager_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
| static int | manager_state_cb (char *context, char *exten, int state, void *data) |
| static struct ast_str * | mxml_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
| static int | process_events (struct mansession *s) |
| static int | process_message (struct mansession *s, const struct message *m) |
| static void | purge_events (void) |
| static void | purge_old_stuff (void *data) |
| cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most | |
| static void | purge_sessions (int n_max) |
| remove at most n_max stale session from the list. | |
| static struct ast_str * | rawman_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
| static void | ref_event (struct eventqent *e) |
| int | reload_manager (void) |
| static int | send_string (struct mansession *s, char *string) |
| static void * | session_do (void *data) |
| The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ). | |
| static int | set_eventmask (struct mansession *s, const char *eventmask) |
| Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm. | |
| static int | strings_to_mask (const char *string) |
| static struct eventqent * | unref_event (struct eventqent *e) |
| static void | xml_copy_escape (struct ast_str **out, const char *src, int mode) |
| static void | xml_translate (struct ast_str **out, char *in, struct ast_variable *vars, enum output_format format) |
| Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'. | |
Variables | |
| static struct server_args | ami_desc |
| tls_config | ami_tls_cfg |
| static struct server_args | amis_desc |
| static int | block_sockets |
| static struct ast_cli_entry | cli_manager [] |
| static char * | contenttype [] |
| static int | displayconnects = 1 |
| static struct manager_action * | first_action |
| list of actions registered | |
| static int | httptimeout = 60 |
| static int | manager_debug |
| ast_http_uri | manageruri |
| ast_http_uri | managerxmluri |
| static char | mandescr_command [] |
| static char | mandescr_events [] |
| static char | mandescr_extensionstate [] |
| static char | mandescr_getconfig [] |
| static char | mandescr_getvar [] |
| static char | mandescr_hangup [] |
| static char | mandescr_listcommands [] |
| static char | mandescr_logoff [] |
| static char | mandescr_mailboxcount [] |
| static char | mandescr_mailboxstatus [] |
| Help text for manager command mailboxstatus. | |
| static char | mandescr_originate [] |
| static char | mandescr_ping [] |
| Manager PING. | |
| static char | mandescr_redirect [] |
| static char | mandescr_sendtext [] |
| static char | mandescr_setvar [] |
| static char | mandescr_timeout [] |
| static char | mandescr_updateconfig [] |
| static char | mandescr_userevent [] |
| static char | mandescr_waitevent [] |
| Manager WAITEVENT. | |
| static int | num_sessions |
| static struct permalias | perms [] |
| ast_http_uri | rawmanuri |
| static int | registered = 0 |
| 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 int | timestampevents |
| static int | webregged = 0 |
|
|
|
|
|
|
|
|
END Doxygen group Definition at line 2483 of file manager.c. 02483 { 02484 FORMAT_RAW, 02485 FORMAT_HTML, 02486 FORMAT_XML, 02487 };
|
|
|
locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket). Definition at line 2500 of file manager.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions. 02501 { 02502 struct mansession *s; 02503 02504 if (ident == 0) 02505 return NULL; 02506 02507 AST_LIST_LOCK(&sessions); 02508 AST_LIST_TRAVERSE(&sessions, s, list) { 02509 ast_mutex_lock(&s->__lock); 02510 if (s->managerid == ident && !s->needdestroy) { 02511 ast_atomic_fetchadd_int(&s->inuse, 1); 02512 break; 02513 } 02514 ast_mutex_unlock(&s->__lock); 02515 } 02516 AST_LIST_UNLOCK(&sessions); 02517 02518 return s; 02519 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 2705 of file manager.c. References ast_variable::name, ast_variable::next, s, and ast_variable::value. Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback(). 02709 { 02710 struct mansession *s = NULL; 02711 unsigned long ident = 0; /* invalid, so find_session will fail if not set through the cookie */ 02712 int blastaway = 0; 02713 struct ast_variable *v; 02714 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 02715 struct ast_str *out = NULL; 02716 struct message m = { 0 }; 02717 unsigned int x; 02718 size_t hdrlen; 02719 02720 for (v = params; v; v = v->next) { 02721 if (!strcasecmp(v->name, "mansession_id")) { 02722 sscanf(v->value, "%lx", &ident); 02723 break; 02724 } 02725 } 02726 02727 if (!(s = find_session(ident))) { 02728 /* Create new session. 02729 * While it is not in the list we don't need any locking 02730 */ 02731 if (!(s = ast_calloc(1, sizeof(*s)))) { 02732 *status = 500; 02733 goto generic_callback_out; 02734 } 02735 s->sin = *requestor; 02736 s->fd = -1; 02737 s->waiting_thread = AST_PTHREADT_NULL; 02738 s->send_events = 0; 02739 ast_mutex_init(&s->__lock); 02740 ast_mutex_lock(&s->__lock); 02741 s->inuse = 1; 02742 s->managerid = rand() | 1; /* make sure it is non-zero */ 02743 s->last_ev = grab_last(); 02744 AST_LIST_LOCK(&sessions); 02745 AST_LIST_INSERT_HEAD(&sessions, s, list); 02746 AST_LIST_UNLOCK(&sessions); 02747 ast_atomic_fetchadd_int(&num_sessions, 1); 02748 } 02749 02750 ast_mutex_unlock(&s->__lock); 02751 02752 if (!(out = ast_str_create(1024))) { 02753 *status = 500; 02754 goto generic_callback_out; 02755 } 02756 02757 s->fd = mkstemp(template); /* create a temporary file for command output */ 02758 unlink(template); 02759 s->f = fdopen(s->fd, "w+"); 02760 02761 for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) { 02762 hdrlen = strlen(v->name) + strlen(v->value) + 3; 02763 m.headers[m.hdrcount] = alloca(hdrlen); 02764 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 02765 m.hdrcount = x + 1; 02766 } 02767 02768 if (process_message(s, &m)) { 02769 if (s->authenticated) { 02770 if (option_verbose > 1) { 02771 if (displayconnects) 02772 ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 02773 } 02774 ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 02775 } else { 02776 if (option_verbose > 1) { 02777 if (displayconnects) 02778 ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr)); 02779 } 02780 ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr)); 02781 } 02782 s->needdestroy = 1; 02783 } 02784 02785 ast_str_append(&out, 0, 02786 "Content-type: text/%s\r\n" 02787 "Cache-Control: no-cache;\r\n" 02788 "Set-Cookie: mansession_id=\"%08lx\"; Version=\"1\"; Max-Age=%d\r\n" 02789 "\r\n", 02790 contenttype[format], 02791 s->managerid, httptimeout); 02792 02793 if (format == FORMAT_XML) { 02794 ast_str_append(&out, 0, "<ajax-response>\n"); 02795 } else if (format == FORMAT_HTML) { 02796 02797 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" 02798 #define TEST_STRING \ 02799 "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ 02800 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ 02801 <input type=\"submit\"></form>" 02802 02803 ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>"); 02804 ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 02805 ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>"); 02806 ast_str_append(&out, 0, ROW_FMT, TEST_STRING); 02807 } 02808 02809 if (s->f != NULL) { /* have temporary output */ 02810 char *buf; 02811 size_t l = ftell(s->f); 02812 02813 if (format == FORMAT_XML || format == FORMAT_HTML) { 02814 if (l) { 02815 if ((buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0))) { 02816 xml_translate(&out, buf, params, format); 02817 munmap(buf, l); 02818 } 02819 } else { 02820 xml_translate(&out, "", params, format); 02821 } 02822 } 02823 fclose(s->f); 02824 s->f = NULL; 02825 s->fd = -1; 02826 } 02827 02828 if (format == FORMAT_XML) { 02829 ast_str_append(&out, 0, "</ajax-response>\n"); 02830 } else if (format == FORMAT_HTML) 02831 ast_str_append(&out, 0, "</table></body>\r\n"); 02832 02833 ast_mutex_lock(&s->__lock); 02834 /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */ 02835 s->sessiontimeout = time(NULL) + ((s->authenticated || httptimeout < 5) ? httptimeout : 5); 02836 02837 if (s->needdestroy) { 02838 if (s->inuse == 1) { 02839 if (option_debug) 02840 ast_log(LOG_DEBUG, "Need destroy, doing it now!\n"); 02841 blastaway = 1; 02842 } else { 02843 if (option_debug) 02844 ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n"); 02845 if (s->waiting_thread != AST_PTHREADT_NULL) 02846 pthread_kill(s->waiting_thread, SIGURG); 02847 s->inuse--; 02848 } 02849 } else 02850 s->inuse--; 02851 ast_mutex_unlock(&s->__lock); 02852 02853 if (blastaway) 02854 destroy_session(s); 02855 generic_callback_out: 02856 if (*status != 200) 02857 return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 02858 return out; 02859 }
|
|
|
Called by Asterisk initialization Definition at line 2931 of file manager.c. References action_challenge(), action_command(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ahp, ami_desc, ami_tls_cfg, amis_desc, append_event(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_load(), ast_extension_state_add(), ast_gethostbyname(), ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), tls_config::certfile, tls_config::cipher, cli_manager, DEFAULT_MANAGER_PORT, enabled, tls_config::enabled, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_USER, free, hp, LOG_NOTICE, manager_state_cb(), mandescr_command, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getvar, mandescr_hangup, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_sendtext, mandescr_setvar, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, server_args::sin, and var. Referenced by reload_manager(). 02932 { 02933 struct ast_config *cfg = NULL; 02934 const char *val; 02935 char *cat = NULL; 02936 int webenabled = 0; 02937 int enabled = 0; 02938 int newhttptimeout = 60; 02939 int have_sslbindaddr = 0; 02940 struct hostent *hp; 02941 struct ast_hostent ahp; 02942 struct ast_manager_user *user = NULL; 02943 struct ast_variable *var; 02944 02945 if (!registered) { 02946 /* Register default actions */ 02947 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 02948 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 02949 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 02950 ast_manager_register2("Login", 0, action_login, "Login Manager", NULL); 02951 ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL); 02952 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 02953 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 02954 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 02955 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 02956 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 02957 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 02958 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 02959 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 02960 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 02961 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 02962 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 02963 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 02964 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 02965 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 02966 ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext); 02967 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 02968 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 02969 02970 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 02971 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 02972 registered = 1; 02973 /* Append placeholder event so master_eventq never runs dry */ 02974 append_event("Event: Placeholder\r\n\r\n", 0); 02975 } 02976 displayconnects = 1; 02977 cfg = ast_config_load("manager.conf"); 02978 if (!cfg) { 02979 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 02980 return 0; 02981 } 02982 02983 /* default values */ 02984 memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in)); 02985 memset(&amis_desc.sin, 0, sizeof(amis_desc.sin)); 02986 amis_desc.sin.sin_port = htons(5039); 02987 ami_desc.sin.sin_port = htons(DEFAULT_MANAGER_PORT); 02988 02989 ami_tls_cfg.enabled = 0; 02990 if (ami_tls_cfg.certfile) 02991 free(ami_tls_cfg.certfile); 02992 ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE); 02993 if (ami_tls_cfg.cipher) 02994 free(ami_tls_cfg.cipher); 02995 ami_tls_cfg.cipher = ast_strdup(""); 02996 02997 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02998 val = var->value; 02999 if (!strcasecmp(var->name, "ssenable")) 03000 ami_tls_cfg.enabled = ast_true(val); 03001 else if (!strcasecmp(var->name, "ssbindport")) 03002 amis_desc.sin.sin_port = htons(atoi(val)); 03003 else if (!strcasecmp(var->name, "ssbindaddr")) { 03004 if ((hp = ast_gethostbyname(val, &ahp))) { 03005 memcpy(&amis_desc.sin.sin_addr, hp->h_addr, sizeof(amis_desc.sin.sin_addr)); 03006 have_sslbindaddr = 1; 03007 } else { 03008 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val); 03009 } 03010 } else if (!strcasecmp(var->name, "sslcert")) { 03011 free(ami_tls_cfg.certfile); 03012 ami_tls_cfg.certfile = ast_strdup(val); 03013 } else if (!strcasecmp(var->name, "sslcipher")) { 03014 free(ami_tls_cfg.cipher); 03015 ami_tls_cfg.cipher = ast_strdup(val); 03016 } else if (!strcasecmp(var->name, "enabled")) { 03017 enabled = ast_true(val); 03018 } else if (!strcasecmp(var->name, "block-sockets")) { 03019 block_sockets = ast_true(val); 03020 } else if (!strcasecmp(var->name, "webenabled")) { 03021 webenabled = ast_true(val); 03022 } else if (!strcasecmp(var->name, "port")) { 03023 ami_desc.sin.sin_port = htons(atoi(val)); 03024 } else if (!strcasecmp(var->name, "bindaddr")) { 03025 if (!inet_aton(val, &ami_desc.sin.sin_addr)) { 03026 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03027 memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr)); 03028 } 03029 } else if (!strcasecmp(var->name, "displayconnects")) { 03030 displayconnects = ast_true(val); 03031 } else if (!strcasecmp(var->name, "timestampevents")) { 03032 timestampevents = ast_true(val); 03033 } else if (!strcasecmp(var->name, "debug")) { 03034 manager_debug = ast_true(val); 03035 } else if (!strcasecmp(var->name, "httptimeout")) { 03036 newhttptimeout = atoi(val); 03037 } else { 03038 ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", 03039 var->name, val); 03040 } 03041 } 03042 03043 if (enabled) 03044 ami_desc.sin.sin_family = AF_INET; 03045 if (!have_sslbindaddr) 03046 amis_desc.sin.sin_addr = ami_desc.sin.sin_addr; 03047 if (ami_tls_cfg.enabled) 03048 amis_desc.sin.sin_family = AF_INET; 03049 03050 03051 AST_LIST_LOCK(&users); 03052 03053 while ((cat = ast_category_browse(cfg, cat))) { 03054 03055 if (!strcasecmp(cat, "general")) 03056 continue; 03057 03058 /* Look for an existing entry, if none found - create one and add it to the list */ 03059 if (!(user = get_manager_by_name_locked(cat))) { 03060 if (!(user = ast_calloc(1, sizeof(*user)))) 03061 break; 03062 /* Copy name over */ 03063 ast_copy_string(user->username, cat, sizeof(user->username)); 03064 /* Insert into list */ 03065 AST_LIST_INSERT_TAIL(&users, user, list); 03066 } 03067 03068 /* Make sure we keep this user and don't destroy it during cleanup */ 03069 user->keep = 1; 03070 03071 var = ast_variable_browse(cfg, cat); 03072 while (var) { 03073 if (!strcasecmp(var->name, "secret")) { 03074 if (user->secret) 03075 free(user->secret); 03076 user->secret = ast_strdup(var->value); 03077 } else if (!strcasecmp(var->name, "deny") ) { 03078 if (user->deny) 03079 free(user->deny); 03080 user->deny = ast_strdup(var->value); 03081 } else if (!strcasecmp(var->name, "permit") ) { 03082 if (user->permit) 03083 free(user->permit); 03084 user->permit = ast_strdup(var->value); 03085 } else if (!strcasecmp(var->name, "read") ) { 03086 if (user->read) 03087 free(user->read); 03088 user->read = ast_strdup(var->value); 03089 } else if (!strcasecmp(var->name, "write") ) { 03090 if (user->write) 03091 free(user->write); 03092 user->write = ast_strdup(var->value); 03093 } else if (!strcasecmp(var->name, "displayconnects") ) 03094 user->displayconnects = ast_true(var->value); 03095 else { 03096 if (option_debug) 03097 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03098 } 03099 var = var->next; 03100 } 03101 } 03102 03103 /* Perform cleanup - essentially prune out old users that no longer exist */ 03104 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03105 if (user->keep) { /* valid record. clear flag for the next round */ 03106 user->keep = 0; 03107 continue; 03108 } 03109 /* We do not need to keep this user so take them out of the list */ 03110 AST_LIST_REMOVE_CURRENT(&users, list); 03111 /* Free their memory now */ 03112 if (user->secret) 03113 free(user->secret); 03114 if (user->deny) 03115 free(user->deny); 03116 if (user->permit) 03117 free(user->permit); 03118 if (user->read) 03119 free(user->read); 03120 if (user->write) 03121 free(user->write); 03122 free(user); 03123 } 03124 AST_LIST_TRAVERSE_SAFE_END 03125 03126 AST_LIST_UNLOCK(&users); 03127 03128 ast_config_destroy(cfg); 03129 03130 if (webenabled && enabled) { 03131 if (!webregged) { 03132 ast_http_uri_link(&rawmanuri); 03133 ast_http_uri_link(&manageruri); 03134 ast_http_uri_link(&managerxmluri); 03135 webregged = 1; 03136 } 03137 } else { 03138 if (webregged) { 03139 ast_http_uri_unlink(&rawmanuri); 03140 ast_http_uri_unlink(&manageruri); 03141 ast_http_uri_unlink(&managerxmluri); 03142 webregged = 0; 03143 } 03144 } 03145 03146 if (newhttptimeout > 0) 03147 httptimeout = newhttptimeout; 03148 03149 server_start(&ami_desc); 03150 if (ssl_setup(amis_desc.tls_cfg)) 03151 server_start(&amis_desc); 03152 return 0; 03153 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 2861 of file manager.c. References FORMAT_HTML, and generic_http_callback(). 02862 { 02863 return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength); 02864 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 2866 of file manager.c. References FORMAT_XML, and generic_http_callback(). 02867 { 02868 return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength); 02869 }
|
|
|
cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
Definition at line 2903 of file manager.c. References purge_events(), and purge_sessions(). 02904 { 02905 purge_sessions(1); 02906 purge_events(); 02907 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 2871 of file manager.c. References FORMAT_RAW, and generic_http_callback(). 02872 { 02873 return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength); 02874 }
|
|
|
Definition at line 3155 of file manager.c. References EVENT_FLAG_SYSTEM, init_manager(), and manager_event. 03156 { 03157 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03158 return init_manager(); 03159 }
|
|
||||||||||||||||
|
Definition at line 2526 of file manager.c. References ast_str_append(), and space. 02527 { 02528 /* store in a local buffer to avoid calling ast_str_append too often */ 02529 char buf[256]; 02530 char *dst = buf; 02531 int space = sizeof(buf); 02532 /* repeat until done and nothing to flush */ 02533 for ( ; *src || dst != buf ; src++) { 02534 if (*src == '\0' || space < 10) { /* flush */ 02535 *dst++ = '\0'; 02536 ast_str_append(out, 0, "%s", buf); 02537 dst = buf; 02538 space = sizeof(buf); 02539 if (*src == '\0') 02540 break; 02541 } 02542 02543 if ( (mode & 2) && !isalnum(*src)) { 02544 *dst++ = '_'; 02545 space--; 02546 continue; 02547 } 02548 switch (*src) { 02549 case '<': 02550 strcpy(dst, "<"); 02551 dst += 4; 02552 space -= 4; 02553 break; 02554 case '>': 02555 strcpy(dst, ">"); 02556 dst += 4; 02557 space -= 4; 02558 break; 02559 case '\"': 02560 strcpy(dst, """); 02561 dst += 6; 02562 space -= 6; 02563 break; 02564 case '\'': 02565 strcpy(dst, "'"); 02566 dst += 6; 02567 space -= 6; 02568 break; 02569 case '&': 02570 strcpy(dst, "&"); 02571 dst += 5; 02572 space -= 5; 02573 break; 02574 02575 default: 02576 *dst++ = mode ? tolower(*src) : *src; 02577 space--; 02578 } 02579 } 02580 }
|
|
||||||||||||||||||||
|
Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'. At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications): General: the unformatted text is used as a value of XML output: to be completed Each section is within <response type="object" id="xxx"> where xxx is taken from ajaxdest variable or defaults to unknown Each row is reported as an attribute Name="value" of an XML entity named from the variable ajaxobjtype, default to "generic" HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a Definition at line 2607 of file manager.c. References FORMAT_XML, ast_variable::name, ast_variable::next, ast_variable::value, and var. 02608 { 02609 struct ast_variable *v; 02610 char *dest = NULL; 02611 char *var, *val; 02612 char *objtype = NULL; 02613 int in_data = 0; /* parsing data */ 02614 int inobj = 0; 02615 int xml = (format == FORMAT_XML); 02616 02617 for (v = vars; v; v = v->next) { 02618 if (!dest && !strcasecmp(v->name, "ajaxdest")) 02619 dest = v->value; 02620 else if (!objtype && !strcasecmp(v->name, "ajaxobjtype")) 02621 objtype = v->value; 02622 } 02623 if (!dest) 02624 dest = "unknown"; 02625 if (!objtype) 02626 objtype = "generic"; 02627 #if 0 02628 /* determine how large is the response. 02629 * This is a heuristic - counting colons (for headers), 02630 * newlines (for extra arguments), and escaped chars. 02631 * XXX needs to be checked carefully for overflows. 02632 * Even better, use some code that allows extensible strings. 02633 */ 02634 for (x = 0; in[x]; x++) { 02635 if (in[x] == ':') 02636 colons++; 02637 else if (in[x] == '\n') 02638 breaks++; 02639 else if (strchr("&\"<>", in[x])) 02640 escaped++; 02641 } 02642 len = (size_t) (1 + strlen(in) + colons * 5 + breaks * (40 + strlen(dest) + strlen(objtype)) + escaped * 10); /* foo="bar", "<response type=\"object\" id=\"dest\"", "&" */ 02643 out = ast_malloc(len); 02644 if (!out) 02645 return NULL; 02646 tmp = out; 02647 *tmp = '\0'; 02648 #endif 02649 /* we want to stop when we find an empty line */ 02650 while (in && *in) { 02651 val = strsep(&in, "\r\n"); /* mark start and end of line */ 02652 if (in && *in == '\n') /* remove trailing \n if any */ 02653 in++; 02654 ast_trim_blanks(val); 02655 if (0) 02656 ast_verbose("inobj %d in_data %d line <%s>\n", inobj, in_data, val); 02657 if (ast_strlen_zero(val)) { 02658 if (in_data) { /* close data */ 02659 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 02660 in_data = 0; 02661 } 02662 ast_str_append(out, 0, xml ? " /></response>\n" : 02663 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 02664 inobj = 0; 02665 continue; 02666 } 02667 /* we expect Name: value lines */ 02668 if (in_data) { 02669 var = NULL; 02670 } else { 02671 var = strsep(&val, ":"); 02672 if (val) { /* found the field name */ 02673 val = ast_skip_blanks(val); 02674 ast_trim_blanks(var); 02675 } else { /* field name not found, move to opaque mode */ 02676 val = var; 02677 var = "Opaque-data"; 02678 } 02679 } 02680 if (!inobj) { 02681 if (xml) 02682 ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype); 02683 else 02684 ast_str_append(out, 0, "<body>\n"); 02685 inobj = 1; 02686 } 02687 if (!in_data) { /* build appropriate line start */ 02688 ast_str_append(out, 0, xml ? " " : "<tr><td>"); 02689 xml_copy_escape(out, var, xml ? 1 | 2 : 0); 02690 ast_str_append(out, 0, xml ? "='" : "</td><td>"); 02691 if (!strcmp(var, "Opaque-data")) 02692 in_data = 1; 02693 } 02694 xml_copy_escape(out, val, 0); /* data field */ 02695 if (!in_data) 02696 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 02697 else 02698 ast_str_append(out, 0, xml ? "\n" : "<br>\n"); 02699 } 02700 if (inobj) 02701 ast_str_append(out, 0, xml ? " /></response>\n" : 02702 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 02703 }
|
|
|
Definition at line 2910 of file manager.c. Referenced by init_manager(). |
|
|
Definition at line 2909 of file manager.c. Referenced by init_manager(). |
|
|
Definition at line 2921 of file manager.c. Referenced by init_manager(). |
|
|
Initial value: {
[FORMAT_RAW] = "plain",
[FORMAT_HTML] = "html",
[FORMAT_XML] = "xml",
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|