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