#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, 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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_info * | ast_module_info = &__mod_info |
static char * | descrip |
enum { ... } | option_flags |
static char * | synopsis = "DISA (Direct Inward System Access)" |
Definition in file app_disa.c.
anonymous enum |
Definition at line 93 of file app_disa.c.
00093 { 00094 NOANSWER_FLAG = (1 << 0), 00095 POUND_TO_END_FLAG = (1 << 1), 00096 } option_flags;
static void __reg_module | ( | void | ) | [static] |
Definition at line 375 of file app_disa.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 375 of file app_disa.c.
static int disa_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 116 of file app_disa.c.
References ast_channel::_state, app_opts, 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(), chan, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, ast_pbx::dtimeoutms, exten, f, firstdigittimeout, ast_flags::flags, ast_channel::hangupcause, LOG_WARNING, mailbox, ast_channel::name, NOANSWER_FLAG, ast_channel::pbx, play_dialtone(), POUND_TO_END_FLAG, and ast_pbx::rtimeoutms.
Referenced by load_module().
00117 { 00118 int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0; 00119 int firstdigittimeout = (chan->pbx ? chan->pbx->rtimeoutms : 20000); 00120 int digittimeout = (chan->pbx ? chan->pbx->dtimeoutms : 10000); 00121 struct ast_flags flags; 00122 char *tmp, exten[AST_MAX_EXTENSION] = "", acctcode[20]=""; 00123 char pwline[256]; 00124 char ourcidname[256],ourcidnum[256]; 00125 struct ast_frame *f; 00126 struct timeval lastdigittime; 00127 int res; 00128 FILE *fp; 00129 AST_DECLARE_APP_ARGS(args, 00130 AST_APP_ARG(passcode); 00131 AST_APP_ARG(context); 00132 AST_APP_ARG(cid); 00133 AST_APP_ARG(mailbox); 00134 AST_APP_ARG(options); 00135 ); 00136 00137 if (ast_strlen_zero(data)) { 00138 ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n"); 00139 return -1; 00140 } 00141 00142 ast_debug(1, "Digittimeout: %d\n", digittimeout); 00143 ast_debug(1, "Responsetimeout: %d\n", firstdigittimeout); 00144 00145 tmp = ast_strdupa(data); 00146 00147 AST_STANDARD_APP_ARGS(args, tmp); 00148 00149 if (ast_strlen_zero(args.context)) 00150 args.context = "disa"; 00151 if (ast_strlen_zero(args.mailbox)) 00152 args.mailbox = ""; 00153 if (!ast_strlen_zero(args.options)) 00154 ast_app_parse_options(app_opts, &flags, NULL, args.options); 00155 00156 ast_debug(1, "Mailbox: %s\n",args.mailbox); 00157 00158 if (!ast_test_flag(&flags, NOANSWER_FLAG)) { 00159 if (chan->_state != AST_STATE_UP) { 00160 /* answer */ 00161 ast_answer(chan); 00162 } 00163 } else special_noanswer = 1; 00164 00165 ast_debug(1, "Context: %s\n",args.context); 00166 00167 if (!strcasecmp(args.passcode, "no-password")) { 00168 k |= 1; /* We have the password */ 00169 ast_debug(1, "DISA no-password login success\n"); 00170 } 00171 00172 lastdigittime = ast_tvnow(); 00173 00174 play_dialtone(chan, args.mailbox); 00175 00176 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 00177 00178 for (;;) { 00179 /* if outa time, give em reorder */ 00180 if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((k&2) ? digittimeout : firstdigittimeout)) { 00181 ast_debug(1,"DISA %s entry timeout on chan %s\n", 00182 ((k&1) ? "extension" : "password"),chan->name); 00183 break; 00184 } 00185 00186 if ((res = ast_waitfor(chan, -1) < 0)) { 00187 ast_debug(1, "Waitfor returned %d\n", res); 00188 continue; 00189 } 00190 00191 if (!(f = ast_read(chan))) { 00192 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 00193 return -1; 00194 } 00195 00196 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { 00197 if (f->data.uint32) 00198 chan->hangupcause = f->data.uint32; 00199 ast_frfree(f); 00200 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 00201 return -1; 00202 } 00203 00204 /* If the frame coming in is not DTMF, just drop it and continue */ 00205 if (f->frametype != AST_FRAME_DTMF) { 00206 ast_frfree(f); 00207 continue; 00208 } 00209 00210 j = f->subclass; /* save digit */ 00211 ast_frfree(f); 00212 00213 if (!i) { 00214 k |= 2; /* We have the first digit */ 00215 ast_playtones_stop(chan); 00216 } 00217 00218 lastdigittime = ast_tvnow(); 00219 00220 /* got a DTMF tone */ 00221 if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */ 00222 if (!(k&1)) { /* if in password state */ 00223 if (j == '#') { /* end of password */ 00224 /* see if this is an integer */ 00225 if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */ 00226 fp = fopen(args.passcode,"r"); 00227 if (!fp) { 00228 ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name); 00229 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 00230 return -1; 00231 } 00232 pwline[0] = 0; 00233 while(fgets(pwline,sizeof(pwline) - 1,fp)) { 00234 if (!pwline[0]) 00235 continue; 00236 if (pwline[strlen(pwline) - 1] == '\n') 00237 pwline[strlen(pwline) - 1] = 0; 00238 if (!pwline[0]) 00239 continue; 00240 /* skip comments */ 00241 if (pwline[0] == '#') 00242 continue; 00243 if (pwline[0] == ';') 00244 continue; 00245 00246 AST_STANDARD_APP_ARGS(args, pwline); 00247 00248 ast_debug(1, "Mailbox: %s\n",args.mailbox); 00249 00250 /* password must be in valid format (numeric) */ 00251 if (sscanf(args.passcode,"%30d", &j) < 1) 00252 continue; 00253 /* if we got it */ 00254 if (!strcmp(exten,args.passcode)) { 00255 if (ast_strlen_zero(args.context)) 00256 args.context = "disa"; 00257 if (ast_strlen_zero(args.mailbox)) 00258 args.mailbox = ""; 00259 break; 00260 } 00261 } 00262 fclose(fp); 00263 } 00264 /* compare the two */ 00265 if (strcmp(exten,args.passcode)) { 00266 ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten); 00267 goto reorder; 00268 00269 } 00270 /* password good, set to dial state */ 00271 ast_debug(1,"DISA on chan %s password is good\n",chan->name); 00272 play_dialtone(chan, args.mailbox); 00273 00274 k|=1; /* In number mode */ 00275 i = 0; /* re-set buffer pointer */ 00276 exten[sizeof(acctcode)] = 0; 00277 ast_copy_string(acctcode, exten, sizeof(acctcode)); 00278 exten[0] = 0; 00279 ast_debug(1,"Successful DISA log-in on chan %s\n", chan->name); 00280 continue; 00281 } 00282 } else { 00283 if (j == '#') { /* end of extension .. maybe */ 00284 if (i == 0 && 00285 (ast_matchmore_extension(chan, args.context, "#", 1, chan->cid.cid_num) || 00286 ast_exists_extension(chan, args.context, "#", 1, chan->cid.cid_num)) ) { 00287 /* Let the # be the part of, or the entire extension */ 00288 } else { 00289 break; 00290 } 00291 } 00292 } 00293 00294 exten[i++] = j; /* save digit */ 00295 exten[i] = 0; 00296 if (!(k&1)) 00297 continue; /* if getting password, continue doing it */ 00298 /* if this exists */ 00299 00300 /* user wants end of number, remove # */ 00301 if (ast_test_flag(&flags, POUND_TO_END_FLAG) && j == '#') { 00302 exten[--i] = 0; 00303 break; 00304 } 00305 00306 if (ast_ignore_pattern(args.context, exten)) { 00307 play_dialtone(chan, ""); 00308 did_ignore = 1; 00309 } else 00310 if (did_ignore) { 00311 ast_playtones_stop(chan); 00312 did_ignore = 0; 00313 } 00314 00315 /* if can do some more, do it */ 00316 if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) { 00317 break; 00318 } 00319 } 00320 } 00321 00322 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 00323 00324 if (k == 3) { 00325 int recheck = 0; 00326 struct ast_flags cdr_flags = { AST_CDR_FLAG_POSTED }; 00327 00328 if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00329 pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten); 00330 exten[0] = 'i'; 00331 exten[1] = '\0'; 00332 recheck = 1; 00333 } 00334 if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00335 ast_playtones_stop(chan); 00336 /* We're authenticated and have a target extension */ 00337 if (!ast_strlen_zero(args.cid)) { 00338 ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum)); 00339 ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum); 00340 } 00341 00342 if (!ast_strlen_zero(acctcode)) 00343 ast_string_field_set(chan, accountcode, acctcode); 00344 00345 if (special_noanswer) cdr_flags.flags = 0; 00346 ast_cdr_reset(chan->cdr, &cdr_flags); 00347 ast_explicit_goto(chan, args.context, exten, 1); 00348 return 0; 00349 } 00350 } 00351 00352 /* Received invalid, but no "i" extension exists in the given context */ 00353 00354 reorder: 00355 /* Play congestion for a bit */ 00356 ast_indicate(chan, AST_CONTROL_CONGESTION); 00357 ast_safe_sleep(chan, 10*1000); 00358 00359 ast_playtones_stop(chan); 00360 00361 return -1; 00362 }
static int load_module | ( | void | ) | [static] |
Definition at line 369 of file app_disa.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application, and disa_exec().
00370 { 00371 return ast_register_application(app, disa_exec, synopsis, descrip) ? 00372 AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS; 00373 }
static void play_dialtone | ( | struct ast_channel * | chan, | |
char * | mailbox | |||
) | [static] |
Definition at line 103 of file app_disa.c.
References ast_app_has_voicemail(), ast_get_indication_tone(), ast_playtones_start(), ast_tonepair_start(), chan, tone_zone_sound::data, and ast_channel::zone.
Referenced by disa_exec().
00104 { 00105 const struct tone_zone_sound *ts = NULL; 00106 if(ast_app_has_voicemail(mailbox, NULL)) 00107 ts = ast_get_indication_tone(chan->zone, "dialrecall"); 00108 else 00109 ts = ast_get_indication_tone(chan->zone, "dial"); 00110 if (ts) 00111 ast_playtones_start(chan, 0, ts->data, 0); 00112 else 00113 ast_tonepair_start(chan, 350, 440, 0, 0); 00114 }
static int unload_module | ( | void | ) | [static] |
Definition at line 364 of file app_disa.c.
References ast_unregister_application().
00365 { 00366 return ast_unregister_application(app); 00367 }
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 375 of file app_disa.c.
char* app = "DISA" [static] |
Definition at line 48 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 101 of file app_disa.c.
Referenced by app_exec(), disa_exec(), record_exec(), and softhangup_exec().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 375 of file app_disa.c.
char* descrip [static] |
Definition at line 52 of file app_disa.c.
enum { ... } option_flags |
char* synopsis = "DISA (Direct Inward System Access)" [static] |
Definition at line 50 of file app_disa.c.