Mon Oct 8 12:39:07 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 = "ac1f6a56484a8820659555499174e588" , .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 417 of file app_disa.c.

static void __unreg_module ( void   )  [static]

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

static int load_module ( void   )  [static]

Definition at line 411 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 406 of file app_disa.c.

References ast_unregister_application().

00407 {
00408    return ast_unregister_application(app);
00409 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 417 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 417 of file app_disa.c.


Generated on Mon Oct 8 12:39:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7