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