astman.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*
00020  *
00021  * ASTerisk MANager
00022  *
00023  */
00024 
00025 /*** MODULEINFO
00026    <support_level>extended</support_level>
00027  ***/
00028 
00029 #include "asterisk.h"
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 429683 $")
00031 #include "asterisk.h"
00032 
00033 #include <newt.h>
00034 #include <stdio.h>
00035 #include <sys/time.h>
00036 #include <netdb.h>
00037 #include <netinet/in.h>
00038 #include <arpa/inet.h>
00039 #include <sys/socket.h>
00040 #include <sys/select.h>
00041 #include <fcntl.h>
00042 #include <string.h>
00043 #include <errno.h>
00044 #include <unistd.h>
00045 #include <stdlib.h>
00046 
00047 #include "asterisk/md5.h"
00048 #include "asterisk/linkedlists.h"
00049 
00050 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
00051 
00052 #undef gethostbyname
00053 
00054 #define MAX_HEADERS 80
00055 #define MAX_LEN 256
00056 
00057 /*
00058  * 2005.05.27 - different versions of newt define the type of the buffer
00059  * for the 5th argument to newtEntry() as char ** or const char ** . To 
00060  * let the code compile cleanly with -Werror, we cast it to void * through 
00061  * _NEWT_CAST.
00062  */
00063 #define _NEWT_CAST (void *)
00064 
00065 #define DEFAULT_MANAGER_PORT 5038
00066 
00067 struct message {
00068    unsigned int hdrcount;
00069    char headers[MAX_HEADERS][MAX_LEN];
00070 };
00071 
00072 static struct ast_mansession {
00073    struct sockaddr_in sin;
00074    int fd;
00075    char inbuf[MAX_LEN];
00076    int inlen;
00077 } session;
00078 
00079 struct ast_chan {
00080    char name[80];
00081    char exten[20];
00082    char context[20];
00083    char priority[20];
00084    char callerid[40];
00085    char state[10];
00086    AST_LIST_ENTRY(ast_chan) list;
00087 };
00088 
00089 static AST_LIST_HEAD_NOLOCK_STATIC(chans, ast_chan);
00090 
00091 /* dummy functions to be compatible with the Asterisk core for md5.c */
00092 void ast_register_file_version(const char *file, const char *version);
00093 void ast_register_file_version(const char *file, const char *version)
00094 {
00095 }
00096 
00097 void ast_unregister_file_version(const char *file);
00098 void ast_unregister_file_version(const char *file)
00099 {
00100 }
00101 
00102 #if !defined(LOW_MEMORY)
00103 int ast_add_profile(const char *, uint64_t scale);
00104 int ast_add_profile(const char *s, uint64_t scale)
00105 {
00106    return -1;
00107 }
00108 
00109 int64_t ast_profile(int, int64_t);
00110 int64_t ast_profile(int key, int64_t val)
00111 {
00112    return 0;
00113 }
00114 int64_t ast_mark(int, int start1_stop0);
00115 int64_t ast_mark(int key, int start1_stop0)
00116 {
00117    return 0;
00118 }
00119 #endif /* LOW_MEMORY */
00120 
00121 /* end of dummy functions */
00122 
00123 static struct ast_chan *find_chan(char *name)
00124 {
00125    struct ast_chan *chan;
00126    AST_LIST_TRAVERSE(&chans, chan, list) {
00127       if (!strcmp(name, chan->name))
00128          return chan;
00129    }
00130    chan = malloc(sizeof(struct ast_chan));
00131    if (chan) {
00132       memset(chan, 0, sizeof(struct ast_chan));
00133       strncpy(chan->name, name, sizeof(chan->name) - 1);
00134       AST_LIST_INSERT_TAIL(&chans, chan, list);
00135    }
00136    return chan;
00137 }
00138 
00139 static void del_chan(char *name)
00140 {
00141    struct ast_chan *chan;
00142 
00143    AST_LIST_TRAVERSE_SAFE_BEGIN(&chans, chan, list) {
00144       if (!strcmp(name, chan->name)) {
00145          AST_LIST_REMOVE_CURRENT(list);
00146          free(chan);
00147          return;
00148       }
00149    }
00150    AST_LIST_TRAVERSE_SAFE_END;
00151 }
00152 
00153 
00154 static void __attribute__((format(printf, 2, 3))) fdprintf(int fd, char *fmt, ...)
00155 {
00156    char stuff[4096];
00157    va_list ap;
00158 
00159    va_start(ap, fmt);
00160    vsnprintf(stuff, sizeof(stuff), fmt, ap);
00161    va_end(ap);
00162    if (write(fd, stuff, strlen(stuff)) < 0) {
00163       fprintf(stderr, "write() failed: %s\n", strerror(errno));
00164    }
00165 }
00166 
00167 static char *get_header(struct message *m, char *var)
00168 {
00169    char cmp[80];
00170    int x;
00171    snprintf(cmp, sizeof(cmp), "%s: ", var);
00172    for (x=0;x<m->hdrcount;x++)
00173       if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
00174          return m->headers[x] + strlen(cmp);
00175    return "";
00176 }
00177 
00178 static int event_newstate(struct ast_mansession *s, struct message *m)
00179 {
00180    struct ast_chan *chan;
00181    chan = find_chan(get_header(m, "Channel"));
00182    strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
00183    return 0;
00184 }
00185 
00186 static int event_newexten(struct ast_mansession *s, struct message *m)
00187 {
00188    struct ast_chan *chan;
00189    chan = find_chan(get_header(m, "Channel"));
00190    strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
00191    strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
00192    strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
00193    return 0;
00194 }
00195 
00196 static int event_newchannel(struct ast_mansession *s, struct message *m)
00197 {
00198    struct ast_chan *chan;
00199    chan = find_chan(get_header(m, "Channel"));
00200    strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
00201    strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
00202    return 0;
00203 }
00204 
00205 static int event_status(struct ast_mansession *s, struct message *m)
00206 {
00207    struct ast_chan *chan;
00208    chan = find_chan(get_header(m, "Channel"));
00209    strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
00210    strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
00211    strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
00212    strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
00213    strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
00214    return 0;
00215 }
00216 
00217 static int event_hangup(struct ast_mansession *s, struct message *m)
00218 {
00219    del_chan(get_header(m, "Channel"));
00220    return 0;
00221 }
00222 
00223 static int event_ignore(struct ast_mansession *s, struct message *m)
00224 {
00225    return 0;
00226 }
00227 
00228 static int event_rename(struct ast_mansession *s, struct message *m)
00229 {
00230    struct ast_chan *chan;
00231    chan = find_chan(get_header(m, "Oldname"));
00232    strncpy(chan->name, get_header(m, "Newname"), sizeof(chan->name) - 1);
00233    return 0;
00234 }
00235 static struct event {
00236    char *event;
00237    int (*func)(struct ast_mansession *s, struct message *m);
00238 } events[] = {
00239    { "Newstate", event_newstate },
00240    { "Newchannel", event_newchannel },
00241    { "Newexten", event_newexten },
00242    { "Hangup", event_hangup },
00243    { "Rename", event_rename },
00244    { "Status", event_status },
00245    { "Link", event_ignore },
00246    { "Unlink", event_ignore },
00247    { "StatusComplete", event_ignore },
00248    { "Dial", event_ignore },
00249    { "PeerStatus", event_ignore },
00250    { "MessageWaiting", event_ignore },
00251    { "Newcallerid", event_ignore },
00252    { "AGIExec", event_ignore},
00253    { "VarSet", event_ignore},
00254    { "MeetmeTalking", event_ignore},
00255    { "MeetmeJoin", event_ignore},
00256    { "MeetmeLeave", event_ignore},
00257    { "MeetmeEnd", event_ignore},
00258    { "MeetmeMute", event_ignore},
00259    { "Masquerade", event_ignore},
00260 };
00261 
00262 static int process_message(struct ast_mansession *s, struct message *m)
00263 {
00264    int x;
00265    char event[80] = "";
00266    strncpy(event, get_header(m, "Event"), sizeof(event) - 1);
00267    if (!strlen(event)) {
00268       fprintf(stderr, "Missing event in request");
00269       return 0;
00270    }
00271    for (x = 0; x < ARRAY_LEN(events); x++) {
00272       if (!strcasecmp(event, events[x].event)) {
00273          if (events[x].func(s, m))
00274             return -1;
00275          break;
00276       }
00277    }
00278    if (x >= ARRAY_LEN(events))
00279       fprintf(stderr, "Ignoring unknown event '%s'", event);
00280 #if 0
00281    for (x=0;x<m->hdrcount;x++) {
00282       printf("Header: %s\n", m->headers[x]);
00283    }
00284 #endif   
00285    return 0;
00286 }
00287 
00288 static void rebuild_channels(newtComponent c)
00289 {
00290    void *prev = NULL;
00291    struct ast_chan *chan;
00292    char tmpn[42];
00293    char tmp[256];
00294    int x=0;
00295    prev = newtListboxGetCurrent(c);
00296    newtListboxClear(c);
00297    AST_LIST_TRAVERSE(&chans, chan, list) {
00298       snprintf(tmpn, sizeof(tmpn), "%s (%s)", chan->name, chan->callerid);
00299       if (strlen(chan->exten)) 
00300          snprintf(tmp, sizeof(tmp), "%-30s %8s -> %s@%s:%s", 
00301             tmpn, chan->state,
00302             chan->exten, chan->context, chan->priority);
00303       else
00304          snprintf(tmp, sizeof(tmp), "%-30s %8s",
00305             tmpn, chan->state);
00306       newtListboxAppendEntry(c, tmp, chan);
00307       x++;
00308    }
00309    if (!x)
00310       newtListboxAppendEntry(c, " << No Active Channels >> ", NULL);
00311    newtListboxSetCurrentByKey(c, prev);
00312 }
00313 
00314 static int has_input(struct ast_mansession *s)
00315 {
00316    int x;
00317    for (x=1;x<s->inlen;x++) 
00318       if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) 
00319          return 1;
00320    return 0;
00321 }
00322 
00323 static int get_input(struct ast_mansession *s, char *output)
00324 {
00325    /* output must have at least sizeof(s->inbuf) space */
00326    int res;
00327    int x;
00328    struct timeval tv = {0, 0};
00329    fd_set fds;
00330    for (x=1;x<s->inlen;x++) {
00331       if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
00332          /* Copy output data up to and including \r\n */
00333          memcpy(output, s->inbuf, x + 1);
00334          /* Add trailing \0 */
00335          output[x+1] = '\0';
00336          /* Move remaining data back to the front */
00337          memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
00338          s->inlen -= (x + 1);
00339          return 1;
00340       }
00341    } 
00342    if (s->inlen >= sizeof(s->inbuf) - 1) {
00343       fprintf(stderr, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
00344       s->inlen = 0;
00345    }
00346    FD_ZERO(&fds);
00347    FD_SET(s->fd, &fds);
00348    res = select(s->fd + 1, &fds, NULL, NULL, &tv);
00349    if (res < 0) {
00350       fprintf(stderr, "Select returned error: %s\n", strerror(errno));
00351    } else if (res > 0) {
00352       res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
00353       if (res < 1)
00354          return -1;
00355       s->inlen += res;
00356       s->inbuf[s->inlen] = '\0';
00357    } else {
00358       return 2;
00359    }
00360    return 0;
00361 }
00362 
00363 static int input_check(struct ast_mansession *s, struct message **mout)
00364 {
00365    static struct message m;
00366    int res;
00367 
00368    if (mout)
00369       *mout = NULL;
00370 
00371    for(;;) {
00372       res = get_input(s, m.headers[m.hdrcount]);
00373       if (res == 1) {
00374 #if 0
00375          fprintf(stderr, "Got header: %s", m.headers[m.hdrcount]);
00376          fgetc(stdin);
00377 #endif
00378          /* Strip trailing \r\n */
00379          if (strlen(m.headers[m.hdrcount]) < 2)
00380             continue;
00381          m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] = '\0';
00382          if (!strlen(m.headers[m.hdrcount])) {
00383             if (mout && strlen(get_header(&m, "Response"))) {
00384                *mout = &m;
00385                return 0;
00386             }
00387             if (process_message(s, &m))
00388                break;
00389             memset(&m, 0, sizeof(m));
00390          } else if (m.hdrcount < MAX_HEADERS - 1)
00391             m.hdrcount++;
00392       } else if (res < 0) {
00393          return -1;
00394       } else if (res == 2)
00395          return 0;
00396    }
00397    return -1;
00398 }
00399 
00400 static struct message *wait_for_response(int timeout)
00401 {
00402    struct message *m;
00403    struct timeval tv;
00404    int res;
00405    fd_set fds;
00406    for (;;) {
00407       tv.tv_sec = timeout / 1000;
00408       tv.tv_usec = (timeout % 1000) * 1000;
00409       FD_SET(session.fd, &fds);
00410       res = select(session.fd + 1, &fds, NULL, NULL, &tv);
00411       if (res < 1)
00412          break;
00413       if (input_check(&session, &m) < 0) {
00414          return NULL;
00415       }
00416       if (m)
00417          return m;
00418    }
00419    return NULL;
00420 }
00421 
00422 
00423 static int __attribute__((format(printf, 2, 3))) manager_action(char *action, char *fmt, ...)
00424 {
00425    struct ast_mansession *s;
00426    char tmp[4096];
00427    va_list ap;
00428    int res;
00429 
00430    s = &session;
00431    fdprintf(s->fd, "Action: %s\r\n", action);
00432    va_start(ap, fmt);
00433    vsnprintf(tmp, sizeof(tmp), fmt, ap);
00434    va_end(ap);
00435    if ((res = write(s->fd, tmp, strlen(tmp))) < 0) {
00436       fprintf(stderr, "write() failed: %s\n", strerror(errno));
00437    }
00438    fdprintf(s->fd, "\r\n");
00439    return 0;
00440 }
00441 
00442 static int show_message(char *title, char *msg)
00443 {
00444    newtComponent form;
00445    newtComponent label;
00446    newtComponent ok;
00447    struct newtExitStruct es;
00448 
00449    newtCenteredWindow(60,7, title);
00450 
00451    label = newtLabel(4,1,msg);
00452    ok = newtButton(27, 3, "OK");
00453    form = newtForm(NULL, NULL, 0);
00454    newtFormAddComponents(form, label, ok, NULL);
00455    newtFormRun(form, &es);
00456    newtPopWindow();
00457    newtFormDestroy(form);
00458    return 0;
00459 }
00460 
00461 static newtComponent showform;
00462 static int show_doing(char *title, char *tmp)
00463 {
00464    struct newtExitStruct es;
00465    newtComponent label;
00466    showform = newtForm(NULL, NULL, 0);
00467    newtCenteredWindow(70,4, title);
00468    label = newtLabel(3,1,tmp);
00469    newtFormAddComponents(showform,label, NULL);
00470    newtFormSetTimer(showform, 200);
00471    newtFormRun(showform, &es);
00472    return 0;
00473 }
00474 
00475 static int hide_doing(void)
00476 {
00477    newtPopWindow();
00478    newtFormDestroy(showform);
00479    return 0;
00480 }
00481 
00482 static void try_status(void)
00483 {
00484    struct message *m;
00485    manager_action("Status", "%s", "");
00486    m = wait_for_response(10000);
00487    if (!m) {
00488       show_message("Status Failed", "Timeout waiting for response");
00489    } else if (strcasecmp(get_header(m, "Response"), "Success"))  {
00490       show_message("Status Failed Failed", get_header(m, "Message"));
00491    }
00492 }
00493    
00494 
00495 static void try_hangup(newtComponent c)
00496 {
00497    struct ast_chan *chan;
00498    struct message *m;
00499 
00500    chan = newtListboxGetCurrent(c);
00501    if (chan) {
00502       manager_action("Hangup", "Channel: %s\r\n", chan->name);
00503       m = wait_for_response(10000);
00504       if (!m) {
00505          show_message("Hangup Failed", "Timeout waiting for response");
00506       } else if (strcasecmp(get_header(m, "Response"), "Success"))  {
00507          show_message("Hangup Failed", get_header(m, "Message"));
00508       }
00509    }
00510    
00511 }
00512 
00513 static int get_user_input(char *msg, char *buf, int buflen)
00514 {
00515    newtComponent form;
00516    newtComponent ok;
00517    newtComponent cancel;
00518    newtComponent inpfield;
00519    const char *input;
00520    int res = -1;
00521    struct newtExitStruct es;
00522 
00523    newtCenteredWindow(60,7, msg);
00524 
00525    inpfield = newtEntry(5, 2, "", 50, _NEWT_CAST &input, 0);
00526    ok = newtButton(22, 3, "OK");
00527    cancel = newtButton(32, 3, "Cancel");
00528    form = newtForm(NULL, NULL, 0);
00529    newtFormAddComponents(form, inpfield, ok, cancel, NULL);
00530    newtFormRun(form, &es);
00531    strncpy(buf, input, buflen - 1);
00532    if (es.u.co == ok) 
00533       res = 0;
00534    else
00535       res = -1;
00536    newtPopWindow();
00537    newtFormDestroy(form);
00538    return res;
00539 }
00540 
00541 static void try_redirect(newtComponent c)
00542 {
00543    struct ast_chan *chan;
00544    char dest[256];
00545    struct message *m;
00546    char channame[256];
00547    char tmp[80];
00548    char *context;
00549 
00550    chan = newtListboxGetCurrent(c);
00551    if (chan) {
00552       strncpy(channame, chan->name, sizeof(channame) - 1);
00553       snprintf(tmp, sizeof(tmp), "Enter new extension for %s", channame);
00554       if (get_user_input(tmp, dest, sizeof(dest))) 
00555          return;
00556       if ((context = strchr(dest, '@'))) {
00557          *context = '\0';
00558          context++;
00559          manager_action("Redirect", "Channel: %s\r\nContext: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name,context,dest);
00560       } else {
00561          manager_action("Redirect", "Channel: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name, dest);
00562       }
00563       m = wait_for_response(10000);
00564       if (!m) {
00565          show_message("Hangup Failed", "Timeout waiting for response");
00566       } else if (strcasecmp(get_header(m, "Response"), "Success"))  {
00567          show_message("Hangup Failed", get_header(m, "Message"));
00568       }
00569    }
00570    
00571 }
00572 
00573 static int manage_calls(char *host)
00574 {
00575    newtComponent form;
00576    newtComponent quit;
00577    newtComponent hangup;
00578    newtComponent redirect;
00579    newtComponent channels;
00580    struct newtExitStruct es;
00581    char tmp[80];
00582 
00583    /* Mark: If there's one thing you learn from this code, it is this...
00584       Never, ever fly Air France.  Their customer service is absolutely
00585       the worst.  I've never heard the words "That's not my problem" as 
00586       many times as I have from their staff -- It should, without doubt
00587       be their corporate motto if it isn't already.  Don't bother giving 
00588       them business because you're just a pain in their side and they
00589       will be sure to let you know the first time you speak to them.
00590       
00591       If you ever want to make me happy just tell me that you, too, will
00592       never fly Air France again either (in spite of their excellent
00593       cuisine). 
00594    
00595       Update by oej: The merger with KLM has transferred this
00596       behaviour to KLM as well. 
00597       Don't bother giving them business either...
00598 
00599       Only if you want to travel randomly without luggage, you
00600       might pick either of them.
00601       
00602    */
00603    snprintf(tmp, sizeof(tmp), "Asterisk Manager at %s", host);
00604    newtCenteredWindow(74, 20, tmp);
00605    form = newtForm(NULL, NULL, 0);
00606    newtFormWatchFd(form, session.fd, NEWT_FD_READ);
00607    newtFormSetTimer(form, 100);
00608    quit = newtButton(62, 16, "Quit");
00609    redirect = newtButton(35, 16, "Redirect");
00610    hangup = newtButton(50, 16, "Hangup");
00611    channels = newtListbox(1,1,14, NEWT_FLAG_SCROLL);
00612    newtFormAddComponents(form, channels, redirect, hangup, quit, NULL);
00613    newtListboxSetWidth(channels, 72);
00614    
00615    show_doing("Getting Status", "Retrieving system status...");
00616    try_status();
00617    hide_doing();
00618 
00619    for(;;) {
00620       newtFormRun(form, &es);
00621       if (has_input(&session) || (es.reason == NEWT_EXIT_FDREADY)) {
00622          if (input_check(&session, NULL)) {
00623             show_message("Disconnected", "Disconnected from remote host");
00624             break;
00625          }
00626       } else if (es.reason == NEWT_EXIT_COMPONENT) {
00627          if (es.u.co == quit)
00628             break;
00629          if (es.u.co == hangup) {
00630             try_hangup(channels);
00631          } else if (es.u.co == redirect) {
00632             try_redirect(channels);
00633          }
00634       }
00635       rebuild_channels(channels);
00636    }
00637    newtFormDestroy(form);
00638    return 0;
00639 }
00640 
00641 static int manager_login(char *hostname)
00642 {
00643    newtComponent form;
00644    newtComponent cancel;
00645    newtComponent login;
00646    newtComponent username;
00647    newtComponent password;
00648    newtComponent label;
00649    newtComponent ulabel;
00650    newtComponent plabel;
00651    const char *user;
00652    const char *pass;
00653    struct message *m;
00654    struct newtExitStruct es;
00655    char tmp[55];
00656    struct hostent *hp;
00657    int res = -1;
00658    
00659    session.fd = socket(AF_INET, SOCK_STREAM, 0);
00660    if (session.fd < 0) {
00661       snprintf(tmp, sizeof(tmp), "socket() failed: %s\n", strerror(errno));
00662       show_message("Socket failed", tmp);
00663       return -1;
00664    }
00665    
00666    snprintf(tmp, sizeof(tmp), "Looking up %s\n", hostname);
00667    show_doing("Connecting....", tmp);
00668    
00669    
00670    hp = gethostbyname(hostname);
00671    if (!hp) {
00672       snprintf(tmp, sizeof(tmp), "No such address: %s\n", hostname);
00673       show_message("Host lookup failed", tmp);
00674       return -1;
00675    }
00676    hide_doing();
00677    snprintf(tmp, sizeof(tmp), "Connecting to %s", hostname);
00678    show_doing("Connecting...", tmp);
00679 
00680    session.sin.sin_family = AF_INET;
00681    session.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
00682    memcpy(&session.sin.sin_addr, hp->h_addr, sizeof(session.sin.sin_addr));
00683 
00684    if (connect(session.fd,(struct sockaddr*)&session.sin, sizeof(session.sin))) {
00685       snprintf(tmp, sizeof(tmp), "%s failed: %s\n", hostname, strerror(errno));
00686       show_message("Connect Failed", tmp);
00687       return -1;
00688    }
00689    
00690    hide_doing();
00691    
00692    login = newtButton(5, 6, "Login");
00693    cancel = newtButton(25, 6, "Cancel");
00694    newtCenteredWindow(40, 10, "Asterisk Manager Login");
00695    snprintf(tmp, sizeof(tmp), "Host:     %s", hostname);
00696    label = newtLabel(4,1, tmp);
00697    
00698    ulabel = newtLabel(4,2,"Username:");
00699    plabel = newtLabel(4,3,"Password:");
00700    
00701    username = newtEntry(14, 2, "", 20, _NEWT_CAST &user, 0);
00702    password = newtEntry(14, 3, "", 20, _NEWT_CAST &pass, NEWT_FLAG_HIDDEN);
00703    
00704    form = newtForm(NULL, NULL, 0);
00705    newtFormAddComponents(form, username, password, login, cancel, label, ulabel, plabel,NULL);
00706    newtFormRun(form, &es);
00707    if (es.reason == NEWT_EXIT_COMPONENT) {
00708       if (es.u.co == login) {
00709          snprintf(tmp, sizeof(tmp), "Logging in '%s'...", user);
00710          show_doing("Logging in", tmp);
00711          /* Check to see if the remote host supports MD5 Authentication */
00712          manager_action("Challenge", "AuthType: MD5\r\n");
00713          m = wait_for_response(10000);
00714          if (m && !strcasecmp(get_header(m, "Response"), "Success")) {
00715             char *challenge = get_header(m, "Challenge");
00716             int x;
00717             int len = 0;
00718             char md5key[256] = "";
00719             struct MD5Context md5;
00720             unsigned char digest[16];
00721             MD5Init(&md5);
00722             MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
00723             MD5Update(&md5, (unsigned char *)pass, strlen(pass));
00724             MD5Final(digest, &md5);
00725             for (x=0; x<16; x++)
00726                len += sprintf(md5key + len, "%02hhx", digest[x]);
00727             manager_action("Login",
00728                   "AuthType: MD5\r\n"
00729                   "Username: %s\r\n"
00730                   "Key: %s\r\n",
00731                   user, md5key);
00732             m = wait_for_response(10000);
00733             hide_doing();
00734             if (!strcasecmp(get_header(m, "Response"), "Success")) {
00735                res = 0;
00736             } else {
00737                show_message("Login Failed", get_header(m, "Message"));
00738             }
00739          } else {
00740             manager_action("Login", 
00741                "Username: %s\r\n"
00742                "Secret: %s\r\n",
00743                   user, pass);
00744             m = wait_for_response(10000);
00745             hide_doing();
00746             if (m) {
00747                if (!strcasecmp(get_header(m, "Response"), "Success")) {
00748                   res = 0;
00749                } else {
00750                   show_message("Login Failed", get_header(m, "Message"));
00751                }
00752             }
00753          }
00754       }
00755    }
00756    newtFormDestroy(form);
00757    return res;
00758 }
00759 
00760 int main(int argc, char *argv[])
00761 {
00762    if (argc < 2) {
00763       fprintf(stderr, "Usage: astman <host>\n");
00764       exit(1);
00765    }
00766    newtInit();
00767    newtCls();
00768    newtDrawRootText(0, 0, "Asterisk Manager (C)2002, Linux Support Services, Inc.");
00769    newtPushHelpLine("Welcome to the Asterisk Manager!");
00770    if (manager_login(argv[1])) {
00771       newtFinished();
00772       exit(1);
00773    }
00774    manage_calls(argv[1]);
00775    newtFinished();
00776    return 0;
00777 }

Generated on Thu Apr 16 06:27:14 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6