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