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, 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 = "0901e4e500243c855563a2d78b0c03e4" , .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 |
| enum { ... } | option_flags |
DISA -- Direct Inward System Access Application.
Definition in file app_disa.c.
| anonymous enum |
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;
| 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_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] |
Definition at line 396 of file app_disa.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and disa_exec().
00397 { 00398 return ast_register_application_xml(app, disa_exec) ? 00399 AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS; 00400 }
| 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 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .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.
Referenced by disa_exec().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 402 of file app_disa.c.
| enum { ... } option_flags |
1.6.2