Sat Aug 6 00:39:34 2011

Asterisk developer's documentation


app_disa.c File Reference

DISA -- Direct Inward System Access Application. More...

#include "asterisk.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
#include "asterisk/indications.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/callerid.h"
#include "asterisk/stringfields.h"

Go to the source code of this file.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int disa_exec (struct ast_channel *chan, void *data)
static int load_module (void)
static void play_dialtone (struct ast_channel *chan, char *mailbox)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DISA (Direct Inward System Access) Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static char * app = "DISA"
static const struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static char * synopsis = "DISA (Direct Inward System Access)"


Detailed Description

DISA -- Direct Inward System Access Application.

Author:
Jim Dixon <jim@lambdatel.com>

Definition in file app_disa.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 399 of file app_disa.c.

static void __unreg_module ( void   )  [static]

Definition at line 399 of file app_disa.c.

static int disa_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 112 of file app_disa.c.

References ast_channel::_state, accountcode, ast_answer(), AST_APP_ARG, ast_callerid_split(), AST_CDR_FLAG_POSTED, ast_cdr_reset(), AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_explicit_goto(), AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_module_user_add, ast_module_user_remove, ast_playtones_stop(), ast_read(), ast_set_callerid(), ast_set_read_format(), ast_set_write_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, ast_pbx::dtimeout, exten, f, firstdigittimeout, ast_flags::flags, LOG_DEBUG, LOG_WARNING, mailbox, ast_channel::name, ast_channel::pbx, pbx_builtin_setvar_helper(), play_dialtone(), and ast_pbx::rtimeout.

Referenced by load_module().

00113 {
00114    int i,j,k,x,did_ignore,special_noanswer;
00115    int firstdigittimeout = 20000;
00116    int digittimeout = 10000;
00117    struct ast_module_user *u;
00118    char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]="";
00119    char pwline[256];
00120    char ourcidname[256],ourcidnum[256];
00121    struct ast_frame *f;
00122    struct timeval lastdigittime;
00123    int res;
00124    time_t rstart;
00125    FILE *fp;
00126    AST_DECLARE_APP_ARGS(args,
00127       AST_APP_ARG(passcode);
00128       AST_APP_ARG(context);
00129       AST_APP_ARG(cid);
00130       AST_APP_ARG(mailbox);
00131       AST_APP_ARG(noanswer);
00132    );
00133 
00134    if (ast_strlen_zero(data)) {
00135       ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
00136       return -1;
00137    }
00138 
00139    u = ast_module_user_add(chan);
00140    
00141    if (chan->pbx) {
00142       firstdigittimeout = chan->pbx->rtimeout*1000;
00143       digittimeout = chan->pbx->dtimeout*1000;
00144    }
00145    
00146    if (ast_set_write_format(chan,AST_FORMAT_ULAW)) {
00147       ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n", chan->name);
00148       ast_module_user_remove(u);
00149       return -1;
00150    }
00151    if (ast_set_read_format(chan,AST_FORMAT_ULAW)) {
00152       ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n", chan->name);
00153       ast_module_user_remove(u);
00154       return -1;
00155    }
00156    
00157    ast_log(LOG_DEBUG, "Digittimeout: %d\n", digittimeout);
00158    ast_log(LOG_DEBUG, "Responsetimeout: %d\n", firstdigittimeout);
00159 
00160    tmp = ast_strdupa(data);
00161 
00162    AST_STANDARD_APP_ARGS(args, tmp);
00163 
00164    if (ast_strlen_zero(args.context)) 
00165       args.context = "disa";  
00166    if (ast_strlen_zero(args.mailbox))
00167       args.mailbox = "";
00168 
00169    ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
00170    
00171 
00172    special_noanswer = 0;
00173    if ((!args.noanswer) || strcmp(args.noanswer,"NOANSWER"))
00174    {
00175       if (chan->_state != AST_STATE_UP) {
00176          /* answer */
00177          ast_answer(chan);
00178       }
00179    } else special_noanswer = 1;
00180    i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
00181    did_ignore = 0;
00182    exten[0] = 0;
00183    acctcode[0] = 0;
00184    /* can we access DISA without password? */ 
00185 
00186    ast_log(LOG_DEBUG, "Context: %s\n",args.context);
00187 
00188    if (!strcasecmp(args.passcode, "no-password")) {
00189       k |= 1; /* We have the password */
00190       ast_log(LOG_DEBUG, "DISA no-password login success\n");
00191    }
00192    lastdigittime = ast_tvnow();
00193 
00194    play_dialtone(chan, args.mailbox);
00195 
00196    for (;;) {
00197         /* if outa time, give em reorder */
00198       if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > 
00199           ((k&2) ? digittimeout : firstdigittimeout)) {
00200          ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
00201             ((k&1) ? "extension" : "password"),chan->name);
00202          break;
00203       }
00204       if ((res = ast_waitfor(chan, -1) < 0)) {
00205          ast_log(LOG_DEBUG, "Waitfor returned %d\n", res);
00206          continue;
00207       }
00208          
00209       f = ast_read(chan);
00210       if (f == NULL) {
00211          ast_module_user_remove(u);
00212          return -1;
00213       }
00214       if ((f->frametype == AST_FRAME_CONTROL) &&
00215           (f->subclass == AST_CONTROL_HANGUP)) {
00216          ast_frfree(f);
00217          ast_module_user_remove(u);
00218          return -1;
00219       }
00220       if (f->frametype == AST_FRAME_VOICE) {
00221          ast_frfree(f);
00222          continue;
00223       }
00224 
00225       /* if not DTMF, just do it again */
00226       if (f->frametype != AST_FRAME_DTMF) {
00227          ast_frfree(f);
00228          continue;
00229       }
00230 
00231       j = f->subclass;  /* save digit */
00232       ast_frfree(f);
00233       if (i == 0) {
00234          k|=2; /* We have the first digit */ 
00235          ast_playtones_stop(chan);
00236       }
00237       lastdigittime = ast_tvnow();
00238         /* got a DTMF tone */
00239       if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
00240          if (!(k&1)) { /* if in password state */
00241             if (j == '#') { /* end of password */
00242                  /* see if this is an integer */
00243                if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */
00244                   fp = fopen(args.passcode,"r");
00245                   if (!fp) {
00246                      ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name);
00247                      ast_module_user_remove(u);
00248                      return -1;
00249                   }
00250                   pwline[0] = 0;
00251                   while(fgets(pwline,sizeof(pwline) - 1,fp)) {
00252                      if (!pwline[0])
00253                         continue;
00254                      if (pwline[strlen(pwline) - 1] == '\n') 
00255                         pwline[strlen(pwline) - 1] = 0;
00256                      if (!pwline[0])
00257                         continue;
00258                       /* skip comments */
00259                      if (pwline[0] == '#')
00260                         continue;
00261                      if (pwline[0] == ';')
00262                         continue;
00263 
00264                      AST_STANDARD_APP_ARGS(args, pwline);
00265          
00266                      ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
00267 
00268                      /* password must be in valid format (numeric) */
00269                      if (sscanf(args.passcode,"%30d", &j) < 1)
00270                         continue;
00271                       /* if we got it */
00272                      if (!strcmp(exten,args.passcode)) {
00273                         if (ast_strlen_zero(args.context))
00274                            args.context = "disa";
00275                         if (ast_strlen_zero(args.mailbox))
00276                            args.mailbox = "";
00277                         break;
00278                      }
00279                   }
00280                   fclose(fp);
00281                }
00282                /* compare the two */
00283                if (strcmp(exten,args.passcode)) {
00284                   ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
00285                   goto reorder;
00286 
00287                }
00288                 /* password good, set to dial state */
00289                ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
00290                play_dialtone(chan, args.mailbox);
00291 
00292                k|=1; /* In number mode */
00293                i = 0;  /* re-set buffer pointer */
00294                exten[sizeof(acctcode)] = 0;
00295                ast_copy_string(acctcode, exten, sizeof(acctcode));
00296                exten[0] = 0;
00297                ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n", chan->name);
00298                continue;
00299             }
00300          } else {
00301             if (j == '#') { /* end of extension .. maybe */
00302                if (i == 0 && 
00303                      (ast_matchmore_extension(chan, args.context, "#", 1, chan->cid.cid_num) ||
00304                       ast_exists_extension(chan, args.context, "#", 1, chan->cid.cid_num)) ) {
00305                   /* Let the # be the part of, or the entire extension */
00306                } else {
00307                   break;
00308                }
00309             }
00310          }
00311 
00312          exten[i++] = j;  /* save digit */
00313          exten[i] = 0;
00314          if (!(k&1))
00315             continue; /* if getting password, continue doing it */
00316          /* if this exists */
00317 
00318          if (ast_ignore_pattern(args.context, exten)) {
00319             play_dialtone(chan, "");
00320             did_ignore = 1;
00321          } else
00322             if (did_ignore) {
00323                ast_playtones_stop(chan);
00324                did_ignore = 0;
00325             }
00326 
00327          /* if can do some more, do it */
00328          if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) {
00329             break;
00330          }
00331       }
00332    }
00333 
00334    if (k == 3) {
00335       int recheck = 0;
00336       struct ast_flags flags = { AST_CDR_FLAG_POSTED };
00337 
00338       if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
00339          pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
00340          exten[0] = 'i';
00341          exten[1] = '\0';
00342          recheck = 1;
00343       }
00344       if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
00345          ast_playtones_stop(chan);
00346          /* We're authenticated and have a target extension */
00347          if (!ast_strlen_zero(args.cid)) {
00348             ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
00349             ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
00350          }
00351 
00352          if (!ast_strlen_zero(acctcode))
00353             ast_string_field_set(chan, accountcode, acctcode);
00354 
00355          if (special_noanswer) flags.flags = 0;
00356          ast_cdr_reset(chan->cdr, &flags);
00357          ast_explicit_goto(chan, args.context, exten, 1);
00358          ast_module_user_remove(u);
00359          return 0;
00360       }
00361    }
00362 
00363    /* Received invalid, but no "i" extension exists in the given context */
00364 
00365 reorder:
00366 
00367    ast_indicate(chan,AST_CONTROL_CONGESTION);
00368    /* something is invalid, give em reorder for several seconds */
00369    time(&rstart);
00370    while(time(NULL) < rstart + 10) {
00371       if (ast_waitfor(chan, -1) < 0)
00372          break;
00373       f = ast_read(chan);
00374       if (!f)
00375          break;
00376       ast_frfree(f);
00377    }
00378    ast_playtones_stop(chan);
00379    ast_module_user_remove(u);
00380    return -1;
00381 }

static int load_module ( void   )  [static]

Definition at line 394 of file app_disa.c.

References ast_register_application(), and disa_exec().

00395 {
00396    return ast_register_application(app, disa_exec, synopsis, descrip);
00397 }

static void play_dialtone ( struct ast_channel chan,
char *  mailbox 
) [static]

Definition at line 99 of file app_disa.c.

References ast_app_has_voicemail(), ast_get_indication_tone(), ast_playtones_start(), ast_tonepair_start(), tone_zone_sound::data, and ast_channel::zone.

Referenced by disa_exec().

00100 {
00101    const struct tone_zone_sound *ts = NULL;
00102    if(ast_app_has_voicemail(mailbox, NULL))
00103       ts = ast_get_indication_tone(chan->zone, "dialrecall");
00104    else
00105       ts = ast_get_indication_tone(chan->zone, "dial");
00106    if (ts)
00107       ast_playtones_start(chan, 0, ts->data, 0);
00108    else
00109       ast_tonepair_start(chan, 350, 440, 0, 0);
00110 }

static int unload_module ( void   )  [static]

Definition at line 383 of file app_disa.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00384 {
00385    int res;
00386 
00387    res = ast_unregister_application(app);
00388 
00389    ast_module_user_hangup_all();
00390 
00391    return res;
00392 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DISA (Direct Inward System Access) Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 399 of file app_disa.c.

char* app = "DISA" [static]

Definition at line 52 of file app_disa.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 399 of file app_disa.c.

char* descrip [static]

Definition at line 56 of file app_disa.c.

char* synopsis = "DISA (Direct Inward System Access)" [static]

Definition at line 54 of file app_disa.c.


Generated on Sat Aug 6 00:39:34 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7