29 #define ASTMM_LIBC ASTMM_IGNORE
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <sys/socket.h>
39 #include <sys/select.h>
49 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
53 #define MAX_HEADERS 80
62 #define _NEWT_CAST (void *)
64 #define DEFAULT_MANAGER_PORT 5038
67 unsigned int hdrcount;
68 char headers[MAX_HEADERS][MAX_LEN];
72 struct sockaddr_in sin;
97 int64_t ast_profile(
int, int64_t);
98 int64_t ast_profile(
int key, int64_t
val)
102 int64_t ast_mark(
int,
int start1_stop0);
103 int64_t ast_mark(
int key,
int start1_stop0)
110 static struct ast_chan *find_chan(
char *name)
114 if (!strcmp(name, chan->name))
117 chan = malloc(
sizeof(
struct ast_chan));
119 memset(chan, 0,
sizeof(
struct ast_chan));
120 strncpy(chan->name, name,
sizeof(chan->name) - 1);
126 static void del_chan(
char *name)
131 if (!strcmp(name, chan->name)) {
141 static void __attribute__((format(printf, 2, 3))) fdprintf(
int fd,
char *fmt, ...)
147 vsnprintf(stuff,
sizeof(stuff), fmt, ap);
149 if (write(fd, stuff, strlen(stuff)) < 0) {
150 fprintf(stderr,
"write() failed: %s\n", strerror(errno));
158 snprintf(cmp,
sizeof(cmp),
"%s: ", var);
159 for (x=0;x<m->hdrcount;x++)
160 if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
161 return m->headers[x] + strlen(cmp);
169 strncpy(chan->state,
get_header(m,
"State"),
sizeof(chan->state) - 1);
177 strncpy(chan->exten,
get_header(m,
"Extension"),
sizeof(chan->exten) - 1);
178 strncpy(chan->context,
get_header(m,
"Context"),
sizeof(chan->context) - 1);
179 strncpy(chan->priority,
get_header(m,
"Priority"),
sizeof(chan->priority) - 1);
187 strncpy(chan->state,
get_header(m,
"State"),
sizeof(chan->state) - 1);
188 strncpy(chan->callerid,
get_header(m,
"Callerid"),
sizeof(chan->callerid) - 1);
196 strncpy(chan->state,
get_header(m,
"State"),
sizeof(chan->state) - 1);
197 strncpy(chan->callerid,
get_header(m,
"Callerid"),
sizeof(chan->callerid) - 1);
198 strncpy(chan->exten,
get_header(m,
"Extension"),
sizeof(chan->exten) - 1);
199 strncpy(chan->context,
get_header(m,
"Context"),
sizeof(chan->context) - 1);
200 strncpy(chan->priority,
get_header(m,
"Priority"),
sizeof(chan->priority) - 1);
219 strncpy(chan->name,
get_header(m,
"Newname"),
sizeof(chan->name) - 1);
226 {
"Newstate", event_newstate },
227 {
"Newchannel", event_newchannel },
228 {
"Newexten", event_newexten },
229 {
"Hangup", event_hangup },
230 {
"Rename", event_rename },
231 {
"Status", event_status },
232 {
"Link", event_ignore },
233 {
"Unlink", event_ignore },
234 {
"StatusComplete", event_ignore },
235 {
"Dial", event_ignore },
236 {
"PeerStatus", event_ignore },
237 {
"MessageWaiting", event_ignore },
238 {
"Newcallerid", event_ignore },
239 {
"AGIExec", event_ignore},
240 {
"VarSet", event_ignore},
241 {
"MeetmeTalking", event_ignore},
242 {
"MeetmeJoin", event_ignore},
243 {
"MeetmeLeave", event_ignore},
244 {
"MeetmeEnd", event_ignore},
245 {
"MeetmeMute", event_ignore},
246 {
"Masquerade", event_ignore},
254 if (!strlen(
event)) {
255 fprintf(stderr,
"Missing event in request");
258 for (x = 0; x < ARRAY_LEN(
events); x++) {
265 if (x >= ARRAY_LEN(
events))
266 fprintf(stderr,
"Ignoring unknown event '%s'", event);
268 for (x=0;x<m->hdrcount;x++) {
269 printf(
"Header: %s\n", m->headers[x]);
275 static void rebuild_channels(newtComponent c)
279 char tmpn[
sizeof(chan->name) +
sizeof(chan->callerid) + 3 - 1];
282 prev = newtListboxGetCurrent(c);
285 snprintf(tmpn,
sizeof(tmpn),
"%s (%s)", chan->name, chan->callerid);
286 if (strlen(chan->exten))
287 snprintf(tmp,
sizeof(tmp),
"%-30s %8s -> %s@%s:%s",
289 chan->exten, chan->context, chan->priority);
291 snprintf(tmp,
sizeof(tmp),
"%-30s %8s",
293 newtListboxAppendEntry(c, tmp, chan);
297 newtListboxAppendEntry(c,
" << No Active Channels >> ", NULL);
298 newtListboxSetCurrentByKey(c, prev);
304 for (x=1;x<s->inlen;x++)
305 if ((s->inbuf[x] ==
'\n') && (s->inbuf[x-1] ==
'\r'))
315 struct timeval tv = {0, 0};
317 for (x=1;x<s->inlen;x++) {
318 if ((s->inbuf[x] ==
'\n') && (s->inbuf[x-1] ==
'\r')) {
320 memcpy(output, s->inbuf, x + 1);
324 memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
329 if (s->inlen >=
sizeof(s->inbuf) - 1) {
330 fprintf(stderr,
"Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
335 res = select(s->fd + 1, &fds, NULL, NULL, &tv);
337 fprintf(stderr,
"Select returned error: %s\n", strerror(errno));
338 }
else if (res > 0) {
339 res = read(s->fd, s->inbuf + s->inlen,
sizeof(s->inbuf) - 1 - s->inlen);
343 s->inbuf[s->inlen] =
'\0';
359 res =
get_input(s, m.headers[m.hdrcount]);
362 fprintf(stderr,
"Got header: %s", m.headers[m.hdrcount]);
366 if (strlen(m.headers[m.hdrcount]) < 2)
368 m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] =
'\0';
369 if (!strlen(m.headers[m.hdrcount])) {
370 if (mout && strlen(
get_header(&m,
"Response"))) {
376 memset(&m, 0,
sizeof(m));
377 }
else if (m.hdrcount < MAX_HEADERS - 1)
379 }
else if (res < 0) {
387 static struct message *wait_for_response(
int timeout)
394 tv.tv_sec = timeout / 1000;
395 tv.tv_usec = (timeout % 1000) * 1000;
396 FD_SET(session.fd, &fds);
397 res = select(session.fd + 1, &fds, NULL, NULL, &tv);
400 if (input_check(&session, &m) < 0) {
410 static int __attribute__((format(printf, 2, 3)))
manager_action(
char *action,
char *fmt, ...)
418 fdprintf(s->fd,
"Action: %s\r\n", action);
420 vsnprintf(tmp,
sizeof(tmp), fmt, ap);
422 if ((res = write(s->fd, tmp, strlen(tmp))) < 0) {
423 fprintf(stderr,
"write() failed: %s\n", strerror(errno));
425 fdprintf(s->fd,
"\r\n");
429 static int show_message(
char *title,
char *msg)
434 struct newtExitStruct es;
436 newtCenteredWindow(60,7, title);
438 label = newtLabel(4,1,msg);
439 ok = newtButton(27, 3,
"OK");
440 form = newtForm(NULL, NULL, 0);
441 newtFormAddComponents(form, label, ok, NULL);
442 newtFormRun(form, &es);
444 newtFormDestroy(form);
448 static newtComponent showform;
449 static int show_doing(
char *title,
char *tmp)
451 struct newtExitStruct es;
453 showform = newtForm(NULL, NULL, 0);
454 newtCenteredWindow(70,4, title);
455 label = newtLabel(3,1,tmp);
456 newtFormAddComponents(showform,label, NULL);
457 newtFormSetTimer(showform, 200);
458 newtFormRun(showform, &es);
462 static int hide_doing(
void)
465 newtFormDestroy(showform);
469 static void try_status(
void)
473 m = wait_for_response(10000);
475 show_message(
"Status Failed",
"Timeout waiting for response");
476 }
else if (strcasecmp(
get_header(m,
"Response"),
"Success")) {
477 show_message(
"Status Failed Failed",
get_header(m,
"Message"));
482 static void try_hangup(newtComponent c)
487 chan = newtListboxGetCurrent(c);
490 m = wait_for_response(10000);
492 show_message(
"Hangup Failed",
"Timeout waiting for response");
493 }
else if (strcasecmp(
get_header(m,
"Response"),
"Success")) {
494 show_message(
"Hangup Failed",
get_header(m,
"Message"));
500 static int get_user_input(
char *msg,
char *buf,
int buflen)
504 newtComponent cancel;
505 newtComponent inpfield;
508 struct newtExitStruct es;
510 newtCenteredWindow(60,7, msg);
512 inpfield = newtEntry(5, 2,
"", 50, _NEWT_CAST &input, 0);
513 ok = newtButton(22, 3,
"OK");
514 cancel = newtButton(32, 3,
"Cancel");
515 form = newtForm(NULL, NULL, 0);
516 newtFormAddComponents(form, inpfield, ok, cancel, NULL);
517 newtFormRun(form, &es);
518 strncpy(buf, input, buflen - 1);
524 newtFormDestroy(form);
528 static void try_redirect(newtComponent c)
533 static const char tmp_prefix[] =
"Enter new extension for ";
535 char tmp[
sizeof(tmp_prefix) +
sizeof(channame)];
538 chan = newtListboxGetCurrent(c);
540 snprintf(channame,
sizeof(channame),
"%s", chan->name);
541 snprintf(tmp,
sizeof(tmp),
"%s%s", tmp_prefix, channame);
542 if (get_user_input(tmp, dest,
sizeof(dest)))
544 if ((context = strchr(dest,
'@'))) {
547 manager_action(
"Redirect",
"Channel: %s\r\nContext: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name,context,dest);
549 manager_action(
"Redirect",
"Channel: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name, dest);
551 m = wait_for_response(10000);
553 show_message(
"Hangup Failed",
"Timeout waiting for response");
554 }
else if (strcasecmp(
get_header(m,
"Response"),
"Success")) {
555 show_message(
"Hangup Failed",
get_header(m,
"Message"));
561 static int manage_calls(
char *host)
565 newtComponent hangup;
566 newtComponent redirect;
567 newtComponent channels;
568 struct newtExitStruct es;
591 snprintf(tmp,
sizeof(tmp),
"Asterisk Manager at %s", host);
592 newtCenteredWindow(74, 20, tmp);
593 form = newtForm(NULL, NULL, 0);
594 newtFormWatchFd(form, session.fd, NEWT_FD_READ);
595 newtFormSetTimer(form, 100);
596 quit = newtButton(62, 16,
"Quit");
597 redirect = newtButton(35, 16,
"Redirect");
598 hangup = newtButton(50, 16,
"Hangup");
599 channels = newtListbox(1,1,14, NEWT_FLAG_SCROLL);
600 newtFormAddComponents(form, channels, redirect, hangup, quit, NULL);
601 newtListboxSetWidth(channels, 72);
603 show_doing(
"Getting Status",
"Retrieving system status...");
608 newtFormRun(form, &es);
609 if (has_input(&session) || (es.reason == NEWT_EXIT_FDREADY)) {
610 if (input_check(&session, NULL)) {
611 show_message(
"Disconnected",
"Disconnected from remote host");
614 }
else if (es.reason == NEWT_EXIT_COMPONENT) {
617 if (es.u.co == hangup) {
618 try_hangup(channels);
619 }
else if (es.u.co == redirect) {
620 try_redirect(channels);
623 rebuild_channels(channels);
625 newtFormDestroy(form);
629 static int manager_login(
char *hostname)
632 newtComponent cancel;
634 newtComponent username;
635 newtComponent password;
637 newtComponent ulabel;
638 newtComponent plabel;
642 struct newtExitStruct es;
647 session.fd = socket(AF_INET, SOCK_STREAM, 0);
648 if (session.fd < 0) {
649 snprintf(tmp,
sizeof(tmp),
"socket() failed: %s\n", strerror(errno));
650 show_message(
"Socket failed", tmp);
654 snprintf(tmp,
sizeof(tmp),
"Looking up %s\n", hostname);
655 show_doing(
"Connecting....", tmp);
658 hp = gethostbyname(hostname);
660 snprintf(tmp,
sizeof(tmp),
"No such address: %s\n", hostname);
661 show_message(
"Host lookup failed", tmp);
665 snprintf(tmp,
sizeof(tmp),
"Connecting to %s", hostname);
666 show_doing(
"Connecting...", tmp);
668 session.sin.sin_family = AF_INET;
669 session.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
670 memcpy(&session.sin.sin_addr, hp->h_addr,
sizeof(session.sin.sin_addr));
672 if (connect(session.fd,(
struct sockaddr*)&session.sin,
sizeof(session.sin))) {
673 snprintf(tmp,
sizeof(tmp),
"%s failed: %s\n", hostname, strerror(errno));
674 show_message(
"Connect Failed", tmp);
680 login = newtButton(5, 6,
"Login");
681 cancel = newtButton(25, 6,
"Cancel");
682 newtCenteredWindow(40, 10,
"Asterisk Manager Login");
683 snprintf(tmp,
sizeof(tmp),
"Host: %s", hostname);
684 label = newtLabel(4,1, tmp);
686 ulabel = newtLabel(4,2,
"Username:");
687 plabel = newtLabel(4,3,
"Password:");
689 username = newtEntry(14, 2,
"", 20, _NEWT_CAST &user, 0);
690 password = newtEntry(14, 3,
"", 20, _NEWT_CAST &pass, NEWT_FLAG_HIDDEN);
692 form = newtForm(NULL, NULL, 0);
693 newtFormAddComponents(form, username, password, login, cancel, label, ulabel, plabel,NULL);
694 newtFormRun(form, &es);
695 if (es.reason == NEWT_EXIT_COMPONENT) {
696 if (es.u.co == login) {
697 snprintf(tmp,
sizeof(tmp),
"Logging in '%s'...", user);
698 show_doing(
"Logging in", tmp);
701 m = wait_for_response(10000);
702 if (m && !strcasecmp(
get_header(m,
"Response"),
"Success")) {
706 char md5key[256] =
"";
708 unsigned char digest[16];
710 MD5Update(&md5, (
unsigned char *)challenge, strlen(challenge));
711 MD5Update(&md5, (
unsigned char *)pass, strlen(pass));
712 MD5Final(digest, &md5);
714 len += sprintf(md5key + len,
"%02hhx", digest[x]);
720 m = wait_for_response(10000);
722 if (!strcasecmp(
get_header(m,
"Response"),
"Success")) {
725 show_message(
"Login Failed",
get_header(m,
"Message"));
732 m = wait_for_response(10000);
735 if (!strcasecmp(
get_header(m,
"Response"),
"Success")) {
738 show_message(
"Login Failed",
get_header(m,
"Message"));
744 newtFormDestroy(form);
748 int main(
int argc,
char *argv[])
751 fprintf(stderr,
"Usage: astman <host>\n");
756 newtDrawRootText(0, 0,
"Asterisk Manager (C)2002, Linux Support Services, Inc.");
757 newtPushHelpLine(
"Welcome to the Asterisk Manager!");
758 if (manager_login(argv[1])) {
762 manage_calls(argv[1]);
static int get_input(struct mansession *s, char *output)
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static int process_message(struct mansession *s, const struct message *m)
Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the ...
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
A set of macros to manage forward-linked lists.
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
structure to hold users read from users.conf
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
int main(int argc, char *argv[])