Thu Oct 11 06:47:34 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"

Include dependency graph for app_disa.c:

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, 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 , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static 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
enum { ... }  option_flags


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 115 of file app_disa.c.

00115      {
00116    NOANSWER_FLAG = (1 << 0),
00117    POUND_TO_END_FLAG = (1 << 1),
00118 } option_flags;


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 402 of file app_disa.c.

static void __unreg_module ( void   )  [static]

Definition at line 402 of file app_disa.c.

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

Definition at line 143 of file app_disa.c.

References ast_channel::_state, accountcode, app_opts, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_callerid_split(), AST_CDR_FLAG_POSTED, ast_cdr_reset(), ast_clear_flag, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_explicit_goto(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_playtones_stop(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, ast_frame::data, ast_pbx::dtimeoutms, exten, f, firstdigittimeout, ast_flags::flags, ast_frame::frametype, ast_channel::hangupcause, LOG_WARNING, mailbox, ast_channel::name, NOANSWER_FLAG, ast_channel::pbx, pbx_builtin_setvar_helper(), play_dialtone(), POUND_TO_END_FLAG, ast_pbx::rtimeoutms, ast_frame::subclass, and ast_frame::uint32.

Referenced by load_module().

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

static int load_module ( void   )  [static]

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

Definition at line 125 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().

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

static int unload_module ( void   )  [static]

Definition at line 391 of file app_disa.c.

References ast_unregister_application().

00392 {
00393    return ast_unregister_application(app);
00394 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 402 of file app_disa.c.

char* app = "DISA" [static]

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

Definition at line 402 of file app_disa.c.

enum { ... } option_flags


Generated on Thu Oct 11 06:47:34 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6