Add micro-http server and abstract manager interface, make snmp not die

on reload.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@14953 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Mark Spencer 20 years ago
parent b0ac62573a
commit 9164eac21a

@ -364,7 +364,7 @@ OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \ astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \ utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \ netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
cryptostub.o sha1.o cryptostub.o sha1.o http.o
# we need to link in the objects statically, not as a library, because # we need to link in the objects statically, not as a library, because
# otherwise modules will not have them available if none of the static # otherwise modules will not have them available if none of the static

@ -3357,7 +3357,7 @@ static void reload_queues(void)
AST_LIST_UNLOCK(&queues); AST_LIST_UNLOCK(&queues);
} }
static int __queues_show(int manager, int fd, int argc, char **argv, int queue_show) static int __queues_show(struct mansession *s, int manager, int fd, int argc, char **argv, int queue_show)
{ {
struct ast_call_queue *q; struct ast_call_queue *q;
struct queue_ent *qe; struct queue_ent *qe;
@ -3381,10 +3381,17 @@ static int __queues_show(int manager, int fd, int argc, char **argv, int queue_s
AST_LIST_LOCK(&queues); AST_LIST_LOCK(&queues);
if (AST_LIST_EMPTY(&queues)) { if (AST_LIST_EMPTY(&queues)) {
AST_LIST_UNLOCK(&queues); AST_LIST_UNLOCK(&queues);
if (queue_show) if (queue_show) {
if (s)
astman_append(s, "No such queue: %s.%s",argv[2], term);
else
ast_cli(fd, "No such queue: %s.%s",argv[2], term); ast_cli(fd, "No such queue: %s.%s",argv[2], term);
} else {
if (s)
astman_append(s, "No queues.%s", term);
else else
ast_cli(fd, "No queues.%s", term); ast_cli(fd, "No queues.%s", term);
}
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
AST_LIST_TRAVERSE(&queues, q, list) { AST_LIST_TRAVERSE(&queues, q, list) {
@ -3409,9 +3416,16 @@ static int __queues_show(int manager, int fd, int argc, char **argv, int queue_s
sl = 0; sl = 0;
if(q->callscompleted > 0) if(q->callscompleted > 0)
sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted);
if (s)
astman_append(s, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds%s",
q->name, q->count, max_buf, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel, term);
else
ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds%s", ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds%s",
q->name, q->count, max_buf, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel, term); q->name, q->count, max_buf, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel, term);
if (q->members) { if (q->members) {
if (s)
astman_append(s, " Members: %s", term);
else
ast_cli(fd, " Members: %s", term); ast_cli(fd, " Members: %s", term);
for (mem = q->members; mem; mem = mem->next) { for (mem = q->members; mem; mem = mem->next) {
max_buf[0] = '\0'; max_buf[0] = '\0';
@ -3429,18 +3443,36 @@ static int __queues_show(int manager, int fd, int argc, char **argv, int queue_s
mem->calls, (long)(time(NULL) - mem->lastcall)); mem->calls, (long)(time(NULL) - mem->lastcall));
} else } else
ast_build_string(&max, &max_left, " has taken no calls yet"); ast_build_string(&max, &max_left, " has taken no calls yet");
if (s)
astman_append(s, " %s%s%s", mem->interface, max_buf, term);
else
ast_cli(fd, " %s%s%s", mem->interface, max_buf, term); ast_cli(fd, " %s%s%s", mem->interface, max_buf, term);
} }
} else } else if (s)
astman_append(s, " No Members%s", term);
else
ast_cli(fd, " No Members%s", term); ast_cli(fd, " No Members%s", term);
if (q->head) { if (q->head) {
pos = 1; pos = 1;
if (s)
astman_append(s, " Callers: %s", term);
else
ast_cli(fd, " Callers: %s", term); ast_cli(fd, " Callers: %s", term);
for (qe = q->head; qe; qe = qe->next) for (qe = q->head; qe; qe = qe->next) {
if (s)
astman_append(s, " %d. %s (wait: %ld:%2.2ld, prio: %d)%s", pos++, qe->chan->name,
(long)(now - qe->start) / 60, (long)(now - qe->start) % 60, qe->prio, term);
else
ast_cli(fd, " %d. %s (wait: %ld:%2.2ld, prio: %d)%s", pos++, qe->chan->name, ast_cli(fd, " %d. %s (wait: %ld:%2.2ld, prio: %d)%s", pos++, qe->chan->name,
(long)(now - qe->start) / 60, (long)(now - qe->start) % 60, qe->prio, term); (long)(now - qe->start) / 60, (long)(now - qe->start) % 60, qe->prio, term);
} else }
} else if (s)
astman_append(s, " No Callers%s", term);
else
ast_cli(fd, " No Callers%s", term); ast_cli(fd, " No Callers%s", term);
if (s)
astman_append(s, "%s", term);
else
ast_cli(fd, "%s", term); ast_cli(fd, "%s", term);
ast_mutex_unlock(&q->lock); ast_mutex_unlock(&q->lock);
if (queue_show) if (queue_show)
@ -3452,12 +3484,12 @@ static int __queues_show(int manager, int fd, int argc, char **argv, int queue_s
static int queues_show(int fd, int argc, char **argv) static int queues_show(int fd, int argc, char **argv)
{ {
return __queues_show(0, fd, argc, argv, 0); return __queues_show(NULL, 0, fd, argc, argv, 0);
} }
static int queue_show(int fd, int argc, char **argv) static int queue_show(int fd, int argc, char **argv)
{ {
return __queues_show(0, fd, argc, argv, 1); return __queues_show(NULL, 0, fd, argc, argv, 1);
} }
static char *complete_queue(const char *line, const char *word, int pos, int state) static char *complete_queue(const char *line, const char *word, int pos, int state)
@ -3485,8 +3517,8 @@ static char *complete_queue(const char *line, const char *word, int pos, int sta
static int manager_queues_show( struct mansession *s, struct message *m ) static int manager_queues_show( struct mansession *s, struct message *m )
{ {
char *a[] = { "show", "queues" }; char *a[] = { "show", "queues" };
__queues_show(1, s->fd, 2, a, 0); __queues_show(s, 1, -1, 2, a, 0);
ast_cli(s->fd, "\r\n\r\n"); /* Properly terminate Manager output */ astman_append(s, "\r\n\r\n"); /* Properly terminate Manager output */
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -3518,7 +3550,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) { if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
if(q->callscompleted > 0) if(q->callscompleted > 0)
sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted);
ast_cli(s->fd, "Event: QueueParams\r\n" astman_append(s, "Event: QueueParams\r\n"
"Queue: %s\r\n" "Queue: %s\r\n"
"Max: %d\r\n" "Max: %d\r\n"
"Calls: %d\r\n" "Calls: %d\r\n"
@ -3535,7 +3567,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
/* List Queue Members */ /* List Queue Members */
for (mem = q->members; mem; mem = mem->next) { for (mem = q->members; mem; mem = mem->next) {
if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) { if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
ast_cli(s->fd, "Event: QueueMember\r\n" astman_append(s, "Event: QueueMember\r\n"
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s\r\n" "Location: %s\r\n"
"Membership: %s\r\n" "Membership: %s\r\n"
@ -3553,7 +3585,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
/* List Queue Entries */ /* List Queue Entries */
pos = 1; pos = 1;
for (qe = q->head; qe; qe = qe->next) { for (qe = q->head; qe; qe = qe->next) {
ast_cli(s->fd, "Event: QueueEntry\r\n" astman_append(s, "Event: QueueEntry\r\n"
"Queue: %s\r\n" "Queue: %s\r\n"
"Position: %d\r\n" "Position: %d\r\n"
"Channel: %s\r\n" "Channel: %s\r\n"
@ -3572,7 +3604,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
} }
AST_LIST_UNLOCK(&queues); AST_LIST_UNLOCK(&queues);
ast_cli(s->fd, astman_append(s,
"Event: QueueStatusComplete\r\n" "Event: QueueStatusComplete\r\n"
"%s" "%s"
"\r\n",idText); "\r\n",idText);

@ -107,6 +107,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h" #include "asterisk/pbx.h"
#include "asterisk/enum.h" #include "asterisk/enum.h"
#include "asterisk/rtp.h" #include "asterisk/rtp.h"
#include "asterisk/http.h"
#if defined(T38_SUPPORT) #if defined(T38_SUPPORT)
#include "asterisk/udptl.h" #include "asterisk/udptl.h"
#endif #endif
@ -1847,7 +1848,8 @@ static int show_cli_help(void) {
return 0; return 0;
} }
static void ast_readconfig(void) { static void ast_readconfig(void)
{
struct ast_config *cfg; struct ast_config *cfg;
struct ast_variable *v; struct ast_variable *v;
char *config = AST_CONFIG_FILE; char *config = AST_CONFIG_FILE;
@ -2321,6 +2323,7 @@ int main(int argc, char *argv[])
printf(term_quit()); printf(term_quit());
exit(1); exit(1);
} }
ast_http_init();
ast_channels_init(); ast_channels_init();
if (init_manager()) { if (init_manager()) {
printf(term_quit()); printf(term_quit());

@ -1411,7 +1411,7 @@ static int action_agents(struct mansession *s, struct message *m)
status = "AGENT_LOGGEDOFF"; status = "AGENT_LOGGEDOFF";
} }
ast_cli(s->fd, "Event: Agents\r\n" astman_append(s, "Event: Agents\r\n"
"Agent: %s\r\n" "Agent: %s\r\n"
"Name: %s\r\n" "Name: %s\r\n"
"Status: %s\r\n" "Status: %s\r\n"
@ -1424,7 +1424,7 @@ static int action_agents(struct mansession *s, struct message *m)
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
} }
AST_LIST_UNLOCK(&agents); AST_LIST_UNLOCK(&agents);
ast_cli(s->fd, "Event: AgentsComplete\r\n" astman_append(s, "Event: AgentsComplete\r\n"
"%s" "%s"
"\r\n",idText); "\r\n",idText);
return 0; return 0;

@ -673,7 +673,7 @@ static void reg_source_db(struct iax2_peer *p);
static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin); static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
static void destroy_peer(struct iax2_peer *peer); static void destroy_peer(struct iax2_peer *peer);
static int ast_cli_netstats(int fd, int limit_fmt); static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt);
#define IAX_IOSTATE_IDLE 0 #define IAX_IOSTATE_IDLE 0
#define IAX_IOSTATE_READY 1 #define IAX_IOSTATE_READY 1
@ -4324,7 +4324,7 @@ static int iax2_show_users(int fd, int argc, char *argv[])
#undef FORMAT2 #undef FORMAT2
} }
static int __iax2_show_peers(int manager, int fd, int argc, char *argv[]) static int __iax2_show_peers(int manager, int fd, struct mansession *s, int argc, char *argv[])
{ {
regex_t regexbuf; regex_t regexbuf;
int havepattern = 0; int havepattern = 0;
@ -4376,6 +4376,9 @@ static int __iax2_show_peers(int manager, int fd, int argc, char *argv[])
} }
ast_mutex_lock(&peerl.lock); ast_mutex_lock(&peerl.lock);
if (s)
astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term);
else
ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term);
for (peer = peerl.peers;peer;peer = peer->next) { for (peer = peerl.peers;peer;peer = peer->next) {
char nm[20]; char nm[20];
@ -4410,6 +4413,14 @@ static int __iax2_show_peers(int manager, int fd, int argc, char *argv[])
ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
peer->encmethods ? "(E)" : " ", status, term); peer->encmethods ? "(E)" : " ", status, term);
if (s)
astman_append(s, FORMAT, name,
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
nm,
ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
peer->encmethods ? "(E)" : " ", status, term);
else
ast_cli(fd, FORMAT, name, ast_cli(fd, FORMAT, name,
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
@ -4420,6 +4431,9 @@ static int __iax2_show_peers(int manager, int fd, int argc, char *argv[])
} }
ast_mutex_unlock(&peerl.lock); ast_mutex_unlock(&peerl.lock);
if (s)
astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
else
ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
if (havepattern) if (havepattern)
@ -4473,12 +4487,12 @@ static int iax2_show_threads(int fd, int argc, char *argv[])
static int iax2_show_peers(int fd, int argc, char *argv[]) static int iax2_show_peers(int fd, int argc, char *argv[])
{ {
return __iax2_show_peers(0, fd, argc, argv); return __iax2_show_peers(0, fd, NULL, argc, argv);
} }
static int manager_iax2_show_netstats( struct mansession *s, struct message *m ) static int manager_iax2_show_netstats( struct mansession *s, struct message *m )
{ {
ast_cli_netstats(s->fd, 0); ast_cli_netstats(s, -1, 0);
ast_cli(s->fd, "\r\n"); astman_append(s, "\r\n");
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -4515,9 +4529,9 @@ static int manager_iax2_show_peers( struct mansession *s, struct message *m )
char *id; char *id;
id = astman_get_header(m,"ActionID"); id = astman_get_header(m,"ActionID");
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id); astman_append(s, "ActionID: %s\r\n",id);
ret = __iax2_show_peers(1, s->fd, 3, a ); ret = __iax2_show_peers(1, -1, s, 3, a );
ast_cli(s->fd, "\r\n\r\n" ); astman_append(s, "\r\n\r\n" );
return ret; return ret;
} /* /JDG */ } /* /JDG */
@ -4651,7 +4665,7 @@ static int iax2_show_channels(int fd, int argc, char *argv[])
#undef FORMATB #undef FORMATB
} }
static int ast_cli_netstats(int fd, int limit_fmt) static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
{ {
int x; int x;
int numchans = 0; int numchans = 0;
@ -4660,9 +4674,17 @@ static int ast_cli_netstats(int fd, int limit_fmt)
if (iaxs[x]) { if (iaxs[x]) {
#ifdef BRIDGE_OPTIMIZATION #ifdef BRIDGE_OPTIMIZATION
if (iaxs[x]->bridgecallno) { if (iaxs[x]->bridgecallno) {
if (limit_fmt) if (limit_fmt) {
if (s)
astman_append(s, "%-25.25s <NATIVE BRIDGED>",
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)");
else
ast_cli(fd, "%-25.25s <NATIVE BRIDGED>", ast_cli(fd, "%-25.25s <NATIVE BRIDGED>",
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)"); iaxs[x]->owner ? iaxs[x]->owner->name : "(None)");
} else {
if (s)
astman_append(s, "%s <NATIVE BRIDGED>",
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)");
else else
ast_cli(fd, "%s <NATIVE BRIDGED>", ast_cli(fd, "%s <NATIVE BRIDGED>",
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)"); iaxs[x]->owner ? iaxs[x]->owner->name : "(None)");
@ -4705,6 +4727,26 @@ static int ast_cli_netstats(int fd, int limit_fmt)
fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
else else
fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
if (s)
astman_append(s, fmt,
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
iaxs[x]->pingtime,
localjitter,
localdelay,
locallost,
locallosspct,
localdropped,
localooo,
iaxs[x]->frames_received/1000,
iaxs[x]->remote_rr.jitter,
iaxs[x]->remote_rr.delay,
iaxs[x]->remote_rr.losscnt,
iaxs[x]->remote_rr.losspct,
iaxs[x]->remote_rr.dropped,
iaxs[x]->remote_rr.ooo,
iaxs[x]->remote_rr.packets/1000);
else
ast_cli(fd, fmt, ast_cli(fd, fmt,
iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
iaxs[x]->pingtime, iaxs[x]->pingtime,
@ -4738,7 +4780,7 @@ static int iax2_show_netstats(int fd, int argc, char *argv[])
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n");
ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n");
numchans = ast_cli_netstats(fd, 1); numchans = ast_cli_netstats(NULL, fd, 1);
ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }

@ -7600,9 +7600,9 @@ static int manager_sip_show_peers( struct mansession *s, struct message *m )
astman_send_ack(s, m, "Peer status list will follow"); astman_send_ack(s, m, "Peer status list will follow");
/* List the peers in separate manager events */ /* List the peers in separate manager events */
_sip_show_peers(s->fd, &total, s, m, 3, a); _sip_show_peers(-1, &total, s, m, 3, a);
/* Send final confirmation */ /* Send final confirmation */
ast_cli(s->fd, astman_append(s,
"Event: PeerlistComplete\r\n" "Event: PeerlistComplete\r\n"
"ListItems: %d\r\n" "ListItems: %d\r\n"
"%s" "%s"
@ -7712,7 +7712,7 @@ static int _sip_show_peers(int fd, int *total, struct mansession *s, struct mess
realtimepeers ? (ast_test_flag(iterator, SIP_REALTIME) ? "Cached RT":"") : ""); realtimepeers ? (ast_test_flag(iterator, SIP_REALTIME) ? "Cached RT":"") : "");
} else { /* Manager format */ } else { /* Manager format */
/* The names here need to be the same as other channels */ /* The names here need to be the same as other channels */
ast_cli(fd, astman_append(s,
"Event: PeerEntry\r\n%s" "Event: PeerEntry\r\n%s"
"Channeltype: SIP\r\n" "Channeltype: SIP\r\n"
"ObjectName: %s\r\n" "ObjectName: %s\r\n"
@ -8031,9 +8031,9 @@ static int manager_sip_show_peer( struct mansession *s, struct message *m )
a[3] = peer; a[3] = peer;
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id); astman_append(s, "ActionID: %s\r\n",id);
ret = _sip_show_peer(1, s->fd, s, m, 4, a ); ret = _sip_show_peer(1, -1, s, m, 4, a );
ast_cli( s->fd, "\r\n\r\n" ); astman_append(s, "\r\n\r\n" );
return ret; return ret;
} }
@ -8067,7 +8067,7 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
peer = find_peer(argv[3], NULL, load_realtime); peer = find_peer(argv[3], NULL, load_realtime);
if (s) { /* Manager */ if (s) { /* Manager */
if (peer) if (peer)
ast_cli(s->fd, "Response: Success\r\n"); astman_append(s, "Response: Success\r\n");
else { else {
snprintf (cbuf, sizeof(cbuf), "Peer %s not found.\n", argv[3]); snprintf (cbuf, sizeof(cbuf), "Peer %s not found.\n", argv[3]);
astman_send_error(s, m, cbuf); astman_send_error(s, m, cbuf);
@ -8161,73 +8161,73 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
} else if (peer && type == 1) { /* manager listing */ } else if (peer && type == 1) { /* manager listing */
char *actionid = astman_get_header(m,"ActionID"); char *actionid = astman_get_header(m,"ActionID");
ast_cli(fd, "Channeltype: SIP\r\n"); astman_append(s, "Channeltype: SIP\r\n");
if (actionid) if (actionid)
ast_cli(fd, "ActionID: %s\r\n", actionid); astman_append(s, "ActionID: %s\r\n", actionid);
ast_cli(fd, "ObjectName: %s\r\n", peer->name); astman_append(s, "ObjectName: %s\r\n", peer->name);
ast_cli(fd, "ChanObjectType: peer\r\n"); astman_append(s, "ChanObjectType: peer\r\n");
ast_cli(fd, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y");
ast_cli(fd, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y");
ast_cli(fd, "Context: %s\r\n", peer->context); astman_append(s, "Context: %s\r\n", peer->context);
ast_cli(fd, "Language: %s\r\n", peer->language); astman_append(s, "Language: %s\r\n", peer->language);
if (!ast_strlen_zero(peer->accountcode)) if (!ast_strlen_zero(peer->accountcode))
ast_cli(fd, "Accountcode: %s\r\n", peer->accountcode); astman_append(s, "Accountcode: %s\r\n", peer->accountcode);
ast_cli(fd, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags));
ast_cli(fd, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres));
if (!ast_strlen_zero(peer->fromuser)) if (!ast_strlen_zero(peer->fromuser))
ast_cli(fd, "SIP-FromUser: %s\r\n", peer->fromuser); astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser);
if (!ast_strlen_zero(peer->fromdomain)) if (!ast_strlen_zero(peer->fromdomain))
ast_cli(fd, "SIP-FromDomain: %s\r\n", peer->fromdomain); astman_append(s, "SIP-FromDomain: %s\r\n", peer->fromdomain);
ast_cli(fd, "Callgroup: "); astman_append(s, "Callgroup: ");
print_group(fd, peer->callgroup, 1); print_group(fd, peer->callgroup, 1);
ast_cli(fd, "Pickupgroup: "); astman_append(s, "Pickupgroup: ");
print_group(fd, peer->pickupgroup, 1); print_group(fd, peer->pickupgroup, 1);
ast_cli(fd, "VoiceMailbox: %s\r\n", peer->mailbox); astman_append(s, "VoiceMailbox: %s\r\n", peer->mailbox);
ast_cli(fd, "LastMsgsSent: %d\r\n", peer->lastmsgssent); astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
ast_cli(fd, "Call limit: %d\r\n", peer->call_limit); astman_append(s, "Call limit: %d\r\n", peer->call_limit);
ast_cli(fd, "Dynamic: %s\r\n", (ast_test_flag((&peer->flags_page2), SIP_PAGE2_DYNAMIC)?"Y":"N")); astman_append(s, "Dynamic: %s\r\n", (ast_test_flag((&peer->flags_page2), SIP_PAGE2_DYNAMIC)?"Y":"N"));
ast_cli(fd, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, ""));
ast_cli(fd, "RegExpire: %ld seconds\r\n", ast_sched_when(sched,peer->expire)); astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched,peer->expire));
ast_cli(fd, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(peer, SIP_INSECURE_PORT), ast_test_flag(peer, SIP_INSECURE_INVITE))); astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(peer, SIP_INSECURE_PORT), ast_test_flag(peer, SIP_INSECURE_INVITE)));
ast_cli(fd, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(peer, SIP_NAT))); astman_append(s, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(peer, SIP_NAT)));
ast_cli(fd, "ACL: %s\r\n", (peer->ha?"Y":"N")); astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N"));
ast_cli(fd, "SIP-CanReinvite: %s\r\n", (ast_test_flag(peer, SIP_CAN_REINVITE)?"Y":"N")); astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(peer, SIP_CAN_REINVITE)?"Y":"N"));
ast_cli(fd, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(peer, SIP_PROMISCREDIR)?"Y":"N")); astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(peer, SIP_PROMISCREDIR)?"Y":"N"));
ast_cli(fd, "SIP-UserPhone: %s\r\n", (ast_test_flag(peer, SIP_USEREQPHONE)?"Y":"N")); astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(peer, SIP_USEREQPHONE)?"Y":"N"));
/* - is enumerated */ /* - is enumerated */
ast_cli(fd, "SIP-DTMFmode %s\r\n", dtmfmode2str(ast_test_flag(peer, SIP_DTMF))); astman_append(s, "SIP-DTMFmode %s\r\n", dtmfmode2str(ast_test_flag(peer, SIP_DTMF)));
ast_cli(fd, "SIPLastMsg: %d\r\n", peer->lastmsg); astman_append(s, "SIPLastMsg: %d\r\n", peer->lastmsg);
ast_cli(fd, "ToHost: %s\r\n", peer->tohost); astman_append(s, "ToHost: %s\r\n", peer->tohost);
ast_cli(fd, "Address-IP: %s\r\nAddress-Port: %d\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port)); astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port));
ast_cli(fd, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
ast_cli(fd, "Default-Username: %s\r\n", peer->username); astman_append(s, "Default-Username: %s\r\n", peer->username);
if (!ast_strlen_zero(global_regcontext)) if (!ast_strlen_zero(global_regcontext))
ast_cli(fd, "RegExtension: %s\r\n", peer->regexten); astman_append(s, "RegExtension: %s\r\n", peer->regexten);
ast_cli(fd, "Codecs: "); astman_append(s, "Codecs: ");
ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
ast_cli(fd, "%s\r\n", codec_buf); astman_append(s, "%s\r\n", codec_buf);
ast_cli(fd, "CodecOrder: "); astman_append(s, "CodecOrder: ");
pref = &peer->prefs; pref = &peer->prefs;
for(x = 0; x < 32 ; x++) { for(x = 0; x < 32 ; x++) {
codec = ast_codec_pref_index(pref,x); codec = ast_codec_pref_index(pref,x);
if (!codec) if (!codec)
break; break;
ast_cli(fd, "%s", ast_getformatname(codec)); astman_append(s, "%s", ast_getformatname(codec));
if (x < 31 && ast_codec_pref_index(pref,x+1)) if (x < 31 && ast_codec_pref_index(pref,x+1))
ast_cli(fd, ","); astman_append(s, ",");
} }
ast_cli(fd, "\r\n"); astman_append(s, "\r\n");
ast_cli(fd, "Status: "); astman_append(s, "Status: ");
peer_status(peer, status, sizeof(status)); peer_status(peer, status, sizeof(status));
ast_cli(fd, "%s\r\n", status); astman_append(s, "%s\r\n", status);
ast_cli(fd, "SIP-Useragent: %s\r\n", peer->useragent); astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent);
ast_cli(fd, "Reg-Contact : %s\r\n", peer->fullcontact); astman_append(s, "Reg-Contact : %s\r\n", peer->fullcontact);
if (peer->chanvars) { if (peer->chanvars) {
for (v = peer->chanvars ; v ; v = v->next) { for (v = peer->chanvars ; v ; v = v->next) {
ast_cli(fd, "ChanVariable:\n"); astman_append(s, "ChanVariable:\n");
ast_cli(fd, " %s,%s\r\n", v->name, v->value); astman_append(s, " %s,%s\r\n", v->name, v->value);
} }
} }

@ -10251,7 +10251,7 @@ static int action_zapshowchannels(struct mansession *s, struct message *m)
while (tmp) { while (tmp) {
if (tmp->channel > 0) { if (tmp->channel > 0) {
int alarm = get_alarms(tmp); int alarm = get_alarms(tmp);
ast_cli(s->fd, astman_append(s,
"Event: ZapShowChannels\r\n" "Event: ZapShowChannels\r\n"
"Channel: %d\r\n" "Channel: %d\r\n"
"Signalling: %s\r\n" "Signalling: %s\r\n"
@ -10270,7 +10270,7 @@ static int action_zapshowchannels(struct mansession *s, struct message *m)
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
ast_cli(s->fd, astman_append(s,
"Event: ZapShowChannelsComplete\r\n" "Event: ZapShowChannelsComplete\r\n"
"%s" "%s"
"\r\n", "\r\n",

@ -0,0 +1,23 @@
;
; Asterisk Builtin mini-HTTP server
;
;
[general]
;
; Whether HTTP interface is enabled or not.
;
enabled=yes
;
; Address to bind to
;
bindaddr=127.0.0.1
;
; Port to bind to
;
bindport=8088
;
; Prefix allows you to specify a prefix for all requests
; to the server. The default is "asterisk" so that all
; requests must begin with /asterisk
;
;prefix=asterisk

@ -568,7 +568,7 @@ static int manager_dbget(struct mansession *s, struct message *m)
astman_send_error(s, m, "Database entry not found"); astman_send_error(s, m, "Database entry not found");
} else { } else {
astman_send_ack(s, m, "Result will follow"); astman_send_ack(s, m, "Result will follow");
ast_cli(s->fd, "Event: DBGetResponse\r\n" astman_append(s, "Event: DBGetResponse\r\n"
"Family: %s\r\n" "Family: %s\r\n"
"Key: %s\r\n" "Key: %s\r\n"
"Val: %s\r\n" "Val: %s\r\n"

463
http.c

@ -0,0 +1,463 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <asterisk/cli.h>
#include <asterisk/http.h>
#include <asterisk/utils.h>
#include <asterisk/strings.h>
#define MAX_PREFIX 80
#define DEFAULT_PREFIX "asterisk"
/* This program implements a tiny http server supporting the "get" method
only and was inspired by micro-httpd by Jef Poskanzer */
struct ast_http_server_instance {
FILE *f;
int fd;
struct sockaddr_in requestor;
ast_http_callback callback;
};
static struct ast_http_uri *uris;
static int httpfd = -1;
static pthread_t master = AST_PTHREADT_NULL;
static char prefix[MAX_PREFIX];
static int prefix_len = 0;
static struct sockaddr_in oldsin;
static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
{
char result[4096];
int reslen = sizeof(result);
char *c=result;
struct ast_variable *v;
char iabuf[INET_ADDRSTRLEN];
ast_build_string(&c, &reslen,
"\r\n"
"<title>Asterisk HTTP Status</title>\r\n"
"<body bgcolor=\"#ffffff\">\r\n"
"<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
"<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), oldsin.sin_addr));
ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
ntohs(oldsin.sin_port));
ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
v = vars;
while(v) {
ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
v = v->next;
}
ast_build_string(&c, &reslen, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n");
return strdup(result);
}
static struct ast_http_uri statusuri = {
.callback = httpstatus_callback,
.description = "Asterisk HTTP General Status",
.uri = "httpstatus",
.has_subtree = 0,
};
char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
{
char *c = NULL;
asprintf(&c,
"Content-type: text/html\r\n"
"%s"
"\r\n"
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
"<html><head>\r\n"
"<title>%d %s</title>\r\n"
"</head><body>\r\n"
"<h1>%s</h1>\r\n"
"<p>%s</p>\r\n"
"<hr />\r\n"
"<address>Asterisk Server</address>\r\n"
"</body></html>\r\n",
(extra_header ? extra_header : ""), status, title, title, text);
return c;
}
int ast_http_uri_link(struct ast_http_uri *urih)
{
struct ast_http_uri *prev=uris;
if (!uris || strlen(uris->uri) <= strlen(urih->uri)) {
urih->next = uris;
uris = urih;
} else {
while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri)))
prev = prev->next;
/* Insert it here */
urih->next = prev->next;
prev->next = urih;
}
return 0;
}
void ast_http_uri_unlink(struct ast_http_uri *urih)
{
struct ast_http_uri *prev = uris;
if (!uris)
return;
if (uris == urih) {
uris = uris->next;
}
while(prev->next) {
if (prev->next == urih) {
prev->next = urih->next;
break;
}
prev = prev->next;
}
}
static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength)
{
char *c;
char *turi;
char *params;
char *var;
char *val;
struct ast_http_uri *urih=NULL;
int len;
struct ast_variable *vars=NULL, *v, *prev = NULL;
if (*uri == '/')
uri++;
params = strchr(uri, '?');
if (params) {
*params = '\0';
params++;
while ((var = strsep(&params, "&"))) {
val = strchr(var, '=');
if (val) {
*val = '\0';
val++;
} else
val = "";
ast_uri_decode(val);
ast_uri_decode(var);
if ((v = ast_variable_new(var, val))) {
if (vars)
prev->next = v;
else
vars = v;
prev = v;
}
}
}
ast_uri_decode(uri);
if (!strncasecmp(uri, prefix, prefix_len)) {
uri += prefix_len;
if (!*uri || (*uri == '/')) {
if (*uri == '/')
uri++;
urih = uris;
while(urih) {
len = strlen(urih->uri);
if (!strncasecmp(urih->uri, uri, len)) {
if (!uri[len] || uri[len] == '/') {
turi = uri + len;
if (*turi == '/')
turi++;
if (!*turi || urih->has_subtree) {
uri = turi;
break;
}
}
}
urih = urih->next;
}
}
}
if (urih) {
c = urih->callback(sin, uri, vars, status, title, contentlength);
ast_variables_destroy(vars);
} else {
c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this serer.");
*status = 404;
*title = strdup("Not Found");
}
return c;
}
static void *ast_httpd_helper_thread(void *data)
{
char buf[4096];
char timebuf[256];
struct ast_http_server_instance *ser = data;
char *uri, *c, *title=NULL;
int status = 200, contentlength = 0;
time_t t;
if (fgets(buf, sizeof(buf), ser->f)) {
/* Skip method */
uri = buf;
while(*uri && (*uri > 32)) uri++;
if (*uri) {
*uri = '\0';
uri++;
}
/* Skip white space */
while (*uri && (*uri < 33)) uri++;
if (*uri) {
c = uri;
while (*c && (*c > 32)) c++;
if (*c) {
*c = '\0';
}
}
if (*uri) {
if (!strcasecmp(buf, "get"))
c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength);
else
c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
} else
c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
if (!c)
c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
if (c) {
time(&t);
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
ast_cli(ser->fd, "HTTP/1.1 GET %d %s\r\n", status, title ? title : "OK");
ast_cli(ser->fd, "Server: Asterisk\r\n");
ast_cli(ser->fd, "Date: %s\r\n", timebuf);
if (contentlength)
ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
ast_cli(ser->fd, "Connection: close\r\n");
ast_cli(ser->fd, "%s", c);
free(c);
}
if (title)
free(title);
}
fclose(ser->f);
free(ser);
return NULL;
}
static void *http_root(void *data)
{
int fd;
struct sockaddr_in sin;
int sinlen;
struct ast_http_server_instance *ser;
pthread_t launched;
for (;;) {
ast_wait_for_input(httpfd, -1);
sinlen = sizeof(sin);
fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
if (fd < 0) {
if ((errno != EAGAIN) && (errno != EINTR))
ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
continue;
}
ser = calloc(1, sizeof(*ser));
if (ser) {
ser->fd = fd;
if ((ser->f = fdopen(ser->fd, "w+"))) {
if (ast_pthread_create(&launched, NULL, ast_httpd_helper_thread, ser)) {
ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
fclose(ser->f);
free(ser);
}
} else {
ast_log(LOG_WARNING, "fdopen failed!\n");
close(ser->fd);
free(ser);
}
} else {
ast_log(LOG_WARNING, "Out of memory!\n");
close(fd);
}
}
return NULL;
}
static void http_server_start(struct sockaddr_in *sin)
{
char iabuf[INET_ADDRSTRLEN];
int flags;
int x = 1;
/* Do nothing if nothing has changed */
if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
ast_log(LOG_DEBUG, "Nothing changed in http\n");
return;
}
memcpy(&oldsin, sin, sizeof(oldsin));
/* Shutdown a running server if there is one */
if (master != AST_PTHREADT_NULL) {
pthread_cancel(master);
pthread_kill(master, SIGURG);
pthread_join(master, NULL);
}
if (httpfd != -1)
close(httpfd);
/* If there's no new server, stop here */
if (!sin->sin_family)
return;
httpfd = socket(AF_INET, SOCK_STREAM, 0);
if (httpfd < 0) {
ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
return;
}
setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port),
strerror(errno));
close(httpfd);
httpfd = -1;
return;
}
if (listen(httpfd, 10)) {
ast_log(LOG_NOTICE, "Unable to listen!\n");
close(httpfd);
httpfd = -1;
return;
}
flags = fcntl(httpfd, F_GETFL);
fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
if (ast_pthread_create(&master, NULL, http_root, NULL)) {
ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port),
strerror(errno));
close(httpfd);
httpfd = -1;
}
}
static int __ast_http_load(int reload)
{
struct ast_config *cfg;
struct ast_variable *v;
int enabled=0;
struct sockaddr_in sin;
struct hostent *hp;
struct ast_hostent ahp;
char newprefix[MAX_PREFIX];
memset(&sin, 0, sizeof(sin));
sin.sin_port = 8088;
strcpy(newprefix, DEFAULT_PREFIX);
cfg = ast_config_load("http.conf");
if (cfg) {
v = ast_variable_browse(cfg, "general");
while(v) {
if (!strcasecmp(v->name, "enabled"))
enabled = ast_true(v->value);
else if (!strcasecmp(v->name, "bindport"))
sin.sin_port = ntohs(atoi(v->value));
else if (!strcasecmp(v->name, "bindaddr")) {
if ((hp = ast_gethostbyname(v->value, &ahp))) {
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
} else {
ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
}
} else if (!strcasecmp(v->name, "prefix"))
ast_copy_string(newprefix, v->value, sizeof(newprefix));
v = v->next;
}
ast_config_destroy(cfg);
}
if (enabled)
sin.sin_family = AF_INET;
if (strcmp(prefix, newprefix)) {
ast_copy_string(prefix, newprefix, sizeof(prefix));
prefix_len = strlen(prefix);
}
http_server_start(&sin);
return 0;
}
static int handle_show_http(int fd, int argc, char *argv[])
{
char iabuf[INET_ADDRSTRLEN];
struct ast_http_uri *urih;
if (argc != 2)
return RESULT_SHOWUSAGE;
ast_cli(fd, "HTTP Server Status:\n");
ast_cli(fd, "Prefix: %s\n", prefix);
if (oldsin.sin_family)
ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), oldsin.sin_addr),
ntohs(oldsin.sin_port));
else
ast_cli(fd, "Server Disabled\n\n");
ast_cli(fd, "Enabled URI's:\n");
urih = uris;
while(urih){
ast_cli(fd, "/%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
urih = urih->next;
}
if (!uris)
ast_cli(fd, "None.\n");
return RESULT_SUCCESS;
}
int ast_http_reload(void)
{
return __ast_http_load(1);
}
static char show_http_help[] =
"Usage: show http\n"
" Shows status of internal HTTP engine\n";
static struct ast_cli_entry http_cli[] = {
{ { "show", "http", NULL }, handle_show_http,
"Display HTTP status", show_http_help },
};
int ast_http_init(void)
{
ast_http_uri_link(&statusuri);
ast_cli_register_multiple(http_cli, sizeof(http_cli) / sizeof(http_cli[0]));
return __ast_http_load(0);
}

@ -0,0 +1,64 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*
* DNS SRV record support
*/
#ifndef _ASTERISK_HTTP_H
#define _ASTERISK_HTTP_H
#include "asterisk/config.h"
/*!
\file http.h
\brief Support for Private Asterisk HTTP Servers.
\note Note: The Asterisk HTTP servers are extremely simple and minimal and
only support the "GET" method.
*/
/* HTTP Callbacks take the socket, the method and the path as arguments and should
return the content, allocated with malloc(). Status should be changed to reflect
the status of the request if it isn't 200 and title may be set to a malloc()'d string
to an appropriate title for non-200 responses. Content length may also be specified.
The return value may include additional headers at the front and MUST include a blank
line with \r\n to provide separation between user headers and content (even if no
content is specified) */
typedef char *(*ast_http_callback)(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength);
struct ast_http_uri {
struct ast_http_uri *next;
const char *description;
const char *uri;
int has_subtree;
ast_http_callback callback;
};
/* Link into the Asterisk HTTP server */
int ast_http_uri_link(struct ast_http_uri *urihandler);
/* Return a malloc()'d string containing an HTTP error message */
char *ast_http_error(int status, const char *title, const char *extra_header, const char *text);
/* Destroy an HTTP server */
void ast_http_uri_unlink(struct ast_http_uri *urihandler);
int ast_http_init(void);
int ast_http_reload(void);
#endif /* _ASTERISK_SRV_H */

@ -64,40 +64,7 @@ struct eventqent {
char eventdata[1]; char eventdata[1];
}; };
struct mansession { struct mansession;
/*! Execution thread */
pthread_t t;
/*! Thread lock -- don't use in action callbacks, it's already taken care of */
ast_mutex_t __lock;
/*! socket address */
struct sockaddr_in sin;
/*! TCP socket */
int fd;
/*! Whether or not we're busy doing an action */
int busy;
/*! Whether or not we're "dead" */
int dead;
/*! Logged in username */
char username[80];
/*! Authentication challenge */
char challenge[10];
/*! Authentication status */
int authenticated;
/*! Authorization for reading */
int readperm;
/*! Authorization for writing */
int writeperm;
/*! Buffer */
char inbuf[AST_MAX_MANHEADER_LEN];
int inlen;
int send_events;
/* Queued events that we've not had the ability to send yet */
struct eventqent *eventq;
/* Timeout for ast_carefulwrite() */
int writetimeout;
struct mansession *next;
};
struct message { struct message {
int hdrcount; int hdrcount;
@ -164,6 +131,10 @@ extern void astman_send_error(struct mansession *s, struct message *m, char *err
extern void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg); extern void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg);
extern void astman_send_ack(struct mansession *s, struct message *m, char *msg); extern void astman_send_ack(struct mansession *s, struct message *m, char *msg);
extern void astman_append(struct mansession *s, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
/*! Called by Asterisk initialization */ /*! Called by Asterisk initialization */
extern int init_manager(void); extern int init_manager(void);
/*! Called by Asterisk initialization */ /*! Called by Asterisk initialization */

@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cdr.h" #include "asterisk/cdr.h"
#include "asterisk/enum.h" #include "asterisk/enum.h"
#include "asterisk/rtp.h" #include "asterisk/rtp.h"
#include "asterisk/http.h"
#include "asterisk/lock.h" #include "asterisk/lock.h"
#ifdef DLFCNCOMPAT #ifdef DLFCNCOMPAT
#include "asterisk/dlfcn-compat.h" #include "asterisk/dlfcn-compat.h"
@ -115,6 +116,7 @@ static struct reload_classes_t {
{ "enum", ast_enum_reload }, { "enum", ast_enum_reload },
{ "manager", reload_manager }, { "manager", reload_manager },
{ "rtp", ast_rtp_reload }, { "rtp", ast_rtp_reload },
{ "http", ast_http_reload },
{ NULL, NULL } { NULL, NULL }
}; };

@ -106,7 +106,40 @@ static struct permalias {
{ 0, "none" }, { 0, "none" },
}; };
static struct mansession *sessions = NULL; static struct mansession {
/*! Execution thread */
pthread_t t;
/*! Thread lock -- don't use in action callbacks, it's already taken care of */
ast_mutex_t __lock;
/*! socket address */
struct sockaddr_in sin;
/*! TCP socket */
int fd;
/*! Whether or not we're busy doing an action */
int busy;
/*! Whether or not we're "dead" */
int dead;
/*! Logged in username */
char username[80];
/*! Authentication challenge */
char challenge[10];
/*! Authentication status */
int authenticated;
/*! Authorization for reading */
int readperm;
/*! Authorization for writing */
int writeperm;
/*! Buffer */
char inbuf[AST_MAX_MANHEADER_LEN];
int inlen;
int send_events;
/* Queued events that we've not had the ability to send yet */
struct eventqent *eventq;
/* Timeout for ast_carefulwrite() */
int writetimeout;
struct mansession *next;
} *sessions = NULL;
static struct manager_action *first_action = NULL; static struct manager_action *first_action = NULL;
AST_MUTEX_DEFINE_STATIC(actionlock); AST_MUTEX_DEFINE_STATIC(actionlock);
@ -182,6 +215,23 @@ static char *complete_show_mancmd(const char *line, const char *word, int pos, i
return NULL; return NULL;
} }
void astman_append(struct mansession *s, const char *fmt, ...)
{
char *stuff;
int res;
va_list ap;
va_start(ap, fmt);
res = vasprintf(&stuff, fmt, ap);
va_end(ap);
if (res == -1) {
ast_log(LOG_ERROR, "Memory allocation failure\n");
} else {
ast_carefulwrite(s->fd, stuff, strlen(stuff), 100);
free(stuff);
}
}
static int handle_showmancmd(int fd, int argc, char *argv[]) static int handle_showmancmd(int fd, int argc, char *argv[])
{ {
struct manager_action *cur = first_action; struct manager_action *cur = first_action;
@ -370,23 +420,23 @@ void astman_send_error(struct mansession *s, struct message *m, char *error)
{ {
char *id = astman_get_header(m,"ActionID"); char *id = astman_get_header(m,"ActionID");
ast_cli(s->fd, "Response: Error\r\n"); astman_append(s, "Response: Error\r\n");
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id); astman_append(s, "ActionID: %s\r\n",id);
ast_cli(s->fd, "Message: %s\r\n\r\n", error); astman_append(s, "Message: %s\r\n\r\n", error);
} }
void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg) void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg)
{ {
char *id = astman_get_header(m,"ActionID"); char *id = astman_get_header(m,"ActionID");
ast_cli(s->fd, "Response: %s\r\n", resp); astman_append(s, "Response: %s\r\n", resp);
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id); astman_append(s, "ActionID: %s\r\n",id);
if (msg) if (msg)
ast_cli(s->fd, "Message: %s\r\n\r\n", msg); astman_append(s, "Message: %s\r\n\r\n", msg);
else else
ast_cli(s->fd, "\r\n"); astman_append(s, "\r\n");
} }
void astman_send_ack(struct mansession *s, struct message *m, char *msg) void astman_send_ack(struct mansession *s, struct message *m, char *msg)
@ -610,15 +660,15 @@ static int action_listcommands(struct mansession *s, struct message *m)
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
snprintf(idText,256,"ActionID: %s\r\n",id); snprintf(idText,256,"ActionID: %s\r\n",id);
ast_cli(s->fd, "Response: Success\r\n%s", idText); astman_append(s, "Response: Success\r\n%s", idText);
ast_mutex_lock(&actionlock); ast_mutex_lock(&actionlock);
while (cur) { /* Walk the list of actions */ while (cur) { /* Walk the list of actions */
if ((s->writeperm & cur->authority) == cur->authority) if ((s->writeperm & cur->authority) == cur->authority)
ast_cli(s->fd, "%s: %s (Priv: %s)\r\n", cur->action, cur->synopsis, authority_to_str(cur->authority, temp, sizeof(temp)) ); astman_append(s, "%s: %s (Priv: %s)\r\n", cur->action, cur->synopsis, authority_to_str(cur->authority, temp, sizeof(temp)) );
cur = cur->next; cur = cur->next;
} }
ast_mutex_unlock(&actionlock); ast_mutex_unlock(&actionlock);
ast_cli(s->fd, "\r\n"); astman_append(s, "\r\n");
return 0; return 0;
} }
@ -758,11 +808,11 @@ static int action_getvar(struct mansession *s, struct message *m)
if (c) if (c)
ast_mutex_unlock(&c->lock); ast_mutex_unlock(&c->lock);
ast_cli(s->fd, "Response: Success\r\n" astman_append(s, "Response: Success\r\n"
"Variable: %s\r\nValue: %s\r\n", varname, varval); "Variable: %s\r\nValue: %s\r\n", varname, varval);
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n",id); astman_append(s, "ActionID: %s\r\n",id);
ast_cli(s->fd, "\r\n"); astman_append(s, "\r\n");
return 0; return 0;
} }
@ -803,7 +853,7 @@ static int action_status(struct mansession *s, struct message *m)
if (c->cdr) { if (c->cdr) {
elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
} }
ast_cli(s->fd, astman_append(s,
"Event: Status\r\n" "Event: Status\r\n"
"Privilege: Call\r\n" "Privilege: Call\r\n"
"Channel: %s\r\n" "Channel: %s\r\n"
@ -826,7 +876,7 @@ static int action_status(struct mansession *s, struct message *m)
ast_state2str(c->_state), c->context, ast_state2str(c->_state), c->context,
c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, idText); c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, idText);
} else { } else {
ast_cli(s->fd, astman_append(s,
"Event: Status\r\n" "Event: Status\r\n"
"Privilege: Call\r\n" "Privilege: Call\r\n"
"Channel: %s\r\n" "Channel: %s\r\n"
@ -849,7 +899,7 @@ static int action_status(struct mansession *s, struct message *m)
break; break;
c = ast_channel_walk_locked(c); c = ast_channel_walk_locked(c);
} }
ast_cli(s->fd, astman_append(s,
"Event: StatusComplete\r\n" "Event: StatusComplete\r\n"
"%s" "%s"
"\r\n",idText); "\r\n",idText);
@ -930,12 +980,12 @@ static int action_command(struct mansession *s, struct message *m)
{ {
char *cmd = astman_get_header(m, "Command"); char *cmd = astman_get_header(m, "Command");
char *id = astman_get_header(m, "ActionID"); char *id = astman_get_header(m, "ActionID");
ast_cli(s->fd, "Response: Follows\r\nPrivilege: Command\r\n"); astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
ast_cli(s->fd, "ActionID: %s\r\n", id); astman_append(s, "ActionID: %s\r\n", id);
/* FIXME: Wedge a ActionID response in here, waiting for later changes */ /* FIXME: Wedge a ActionID response in here, waiting for later changes */
ast_cli_command(s->fd, cmd); ast_cli_command(s->fd, cmd);
ast_cli(s->fd, "--END COMMAND--\r\n\r\n"); astman_append(s, "--END COMMAND--\r\n\r\n");
return 0; return 0;
} }
@ -1130,7 +1180,7 @@ static int action_mailboxstatus(struct mansession *s, struct message *m)
if (!ast_strlen_zero(id)) if (!ast_strlen_zero(id))
snprintf(idText,256,"ActionID: %s\r\n",id); snprintf(idText,256,"ActionID: %s\r\n",id);
ret = ast_app_has_voicemail(mailbox, NULL); ret = ast_app_has_voicemail(mailbox, NULL);
ast_cli(s->fd, "Response: Success\r\n" astman_append(s, "Response: Success\r\n"
"%s" "%s"
"Message: Mailbox Status\r\n" "Message: Mailbox Status\r\n"
"Mailbox: %s\r\n" "Mailbox: %s\r\n"
@ -1163,7 +1213,7 @@ static int action_mailboxcount(struct mansession *s, struct message *m)
if (!ast_strlen_zero(id)) { if (!ast_strlen_zero(id)) {
snprintf(idText,256,"ActionID: %s\r\n",id); snprintf(idText,256,"ActionID: %s\r\n",id);
} }
ast_cli(s->fd, "Response: Success\r\n" astman_append(s, "Response: Success\r\n"
"%s" "%s"
"Message: Mailbox Message Count\r\n" "Message: Mailbox Message Count\r\n"
"Mailbox: %s\r\n" "Mailbox: %s\r\n"
@ -1204,7 +1254,7 @@ static int action_extensionstate(struct mansession *s, struct message *m)
if (!ast_strlen_zero(id)) { if (!ast_strlen_zero(id)) {
snprintf(idText,256,"ActionID: %s\r\n",id); snprintf(idText,256,"ActionID: %s\r\n",id);
} }
ast_cli(s->fd, "Response: Success\r\n" astman_append(s, "Response: Success\r\n"
"%s" "%s"
"Message: Extension Status\r\n" "Message: Extension Status\r\n"
"Exten: %s\r\n" "Exten: %s\r\n"
@ -1272,7 +1322,7 @@ static int process_message(struct mansession *s, struct message *m)
if (ast_strlen_zero(s->challenge)) if (ast_strlen_zero(s->challenge))
snprintf(s->challenge, sizeof(s->challenge), "%d", rand()); snprintf(s->challenge, sizeof(s->challenge), "%d", rand());
ast_mutex_lock(&s->__lock); ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Response: Success\r\n" astman_append(s, "Response: Success\r\n"
"%s" "%s"
"Challenge: %s\r\n\r\n", "Challenge: %s\r\n\r\n",
idText,s->challenge); idText,s->challenge);
@ -1396,7 +1446,7 @@ static void *session_do(void *data)
int res; int res;
ast_mutex_lock(&s->__lock); ast_mutex_lock(&s->__lock);
ast_cli(s->fd, "Asterisk Call Manager/1.0\r\n"); astman_append(s, "Asterisk Call Manager/1.0\r\n");
ast_mutex_unlock(&s->__lock); ast_mutex_unlock(&s->__lock);
memset(&m, 0, sizeof(m)); memset(&m, 0, sizeof(m));
for (;;) { for (;;) {

@ -1897,7 +1897,7 @@ static int manager_parking_status( struct mansession *s, struct message *m )
cur=parkinglot; cur=parkinglot;
while(cur) { while(cur) {
ast_cli(s->fd, "Event: ParkedCall\r\n" astman_append(s, "Event: ParkedCall\r\n"
"Exten: %d\r\n" "Exten: %d\r\n"
"Channel: %s\r\n" "Channel: %s\r\n"
"From: %s\r\n" "From: %s\r\n"
@ -1915,7 +1915,7 @@ static int manager_parking_status( struct mansession *s, struct message *m )
cur = cur->next; cur = cur->next;
} }
ast_cli(s->fd, astman_append(s,
"Event: ParkedCallsComplete\r\n" "Event: ParkedCallsComplete\r\n"
"%s" "%s"
"\r\n",idText); "\r\n",idText);

@ -31,7 +31,7 @@ int res_snmp_agentx_subagent;
int res_snmp_dont_stop; int res_snmp_dont_stop;
int res_snmp_enabled; int res_snmp_enabled;
static pthread_t thread; static pthread_t thread = AST_PTHREADT_NULL;
static int load_config(void) static int load_config(void)
{ {
@ -111,8 +111,9 @@ int reload(void)
ast_verbose(VERBOSE_PREFIX_1 "Reloading [Sub]Agent Module\n"); ast_verbose(VERBOSE_PREFIX_1 "Reloading [Sub]Agent Module\n");
res_snmp_dont_stop = 0; res_snmp_dont_stop = 0;
if (thread != AST_PTHREADT_NULL)
pthread_join(thread, NULL); pthread_join(thread, NULL);
thread = AST_PTHREADT_NULL;
load_config(); load_config();
res_snmp_dont_stop = 1; res_snmp_dont_stop = 1;

Loading…
Cancel
Save