Sat Mar 10 01:54:31 2012

Asterisk developer's documentation


app_disa.c File Reference

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

#include "asterisk.h"
#include <math.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.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.

Enumerations

enum  { NOANSWER_FLAG = (1 << 0), POUND_TO_END_FLAG = (1 << 1) }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int disa_exec (struct ast_channel *chan, const char *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_LOAD_ORDER , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static const char app [] = "DISA"
static struct ast_app_option app_opts [128] = { [ 'n' ] = { .flag = NOANSWER_FLAG }, [ 'p' ] = { .flag = POUND_TO_END_FLAG },}
static struct ast_module_infoast_module_info = &__mod_info


Detailed Description

DISA -- Direct Inward System Access Application.

Author:
Jim Dixon <jim@lambdatel.com>

Definition in file app_disa.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
NOANSWER_FLAG 
POUND_TO_END_FLAG 

Definition at line 119 of file app_disa.c.

00119      {
00120    NOANSWER_FLAG = (1 << 0),
00121    POUND_TO_END_FLAG = (1 << 1),
00122 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 412 of file app_disa.c.

static void __unreg_module ( void   )  [static]

Definition at line 412 of file app_disa.c.

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

Definition at line 147 of file app_disa.c.

References ast_channel::_state, app_opts, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_clear_flag, AST_CONTROL_HANGUP, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_playtones_stop(), ast_read(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_channel::caller, context, ast_pbx::dtimeoutms, exten, f, firstdigittimeout, ast_flags::flags, ast_channel::hangupcause, ast_party_caller::id, LOG_WARNING, mailbox, ast_channel::name, NOANSWER_FLAG, ast_party_id::number, ast_channel::pbx, play_dialtone(), POUND_TO_END_FLAG, ast_pbx::rtimeoutms, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by load_module().

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

static int load_module ( void   )  [static]

Definition at line 406 of file app_disa.c.

References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and disa_exec().

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

Definition at line 129 of file app_disa.c.

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

Referenced by disa_exec().

00130 {
00131    struct ast_tone_zone_sound *ts = NULL;
00132 
00133    if (ast_app_has_voicemail(mailbox, NULL)) {
00134       ts = ast_get_indication_tone(chan->zone, "dialrecall");
00135    } else {
00136       ts = ast_get_indication_tone(chan->zone, "dial");
00137    }
00138 
00139    if (ts) {
00140       ast_playtones_start(chan, 0, ts->data, 0);
00141       ts = ast_tone_zone_sound_unref(ts);
00142    } else {
00143       ast_tonepair_start(chan, 350, 440, 0, 0);
00144    }
00145 }

static int unload_module ( void   )  [static]

Definition at line 401 of file app_disa.c.

References ast_unregister_application().

00402 {
00403    return ast_unregister_application(app);
00404 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 412 of file app_disa.c.

const char app[] = "DISA" [static]

Definition at line 117 of file app_disa.c.

struct ast_app_option app_opts[128] = { [ 'n' ] = { .flag = NOANSWER_FLAG }, [ 'p' ] = { .flag = POUND_TO_END_FLAG },} [static]

Definition at line 127 of file app_disa.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 412 of file app_disa.c.


Generated on Sat Mar 10 01:54:31 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7