#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"
Include dependency graph for app_disa.c:
Go to the source code of this file.
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"DISA (Direct Inward System Access) Application") | |
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 char * | app = "DISA" |
static char * | descrip |
static char * | synopsis = "DISA (Direct Inward System Access)" |
Definition in file app_disa.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"DISA (Direct Inward System Access) Application" | ||||
) |
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_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_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::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,"%d",&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,"%d", &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 */ 00302 break; 00303 } 00304 } 00305 00306 exten[i++] = j; /* save digit */ 00307 exten[i] = 0; 00308 if (!(k&1)) 00309 continue; /* if getting password, continue doing it */ 00310 /* if this exists */ 00311 00312 if (ast_ignore_pattern(args.context, exten)) { 00313 play_dialtone(chan, ""); 00314 did_ignore = 1; 00315 } else 00316 if (did_ignore) { 00317 ast_playtones_stop(chan); 00318 did_ignore = 0; 00319 } 00320 00321 /* if can do some more, do it */ 00322 if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) { 00323 break; 00324 } 00325 } 00326 } 00327 00328 if (k == 3) { 00329 int recheck = 0; 00330 struct ast_flags flags = { AST_CDR_FLAG_POSTED }; 00331 00332 if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00333 pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten); 00334 exten[0] = 'i'; 00335 exten[1] = '\0'; 00336 recheck = 1; 00337 } 00338 if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00339 ast_playtones_stop(chan); 00340 /* We're authenticated and have a target extension */ 00341 if (!ast_strlen_zero(args.cid)) { 00342 ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum)); 00343 ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum); 00344 } 00345 00346 if (!ast_strlen_zero(acctcode)) 00347 ast_string_field_set(chan, accountcode, acctcode); 00348 00349 if (special_noanswer) flags.flags = 0; 00350 ast_cdr_reset(chan->cdr, &flags); 00351 ast_explicit_goto(chan, args.context, exten, 1); 00352 ast_module_user_remove(u); 00353 return 0; 00354 } 00355 } 00356 00357 /* Received invalid, but no "i" extension exists in the given context */ 00358 00359 reorder: 00360 00361 ast_indicate(chan,AST_CONTROL_CONGESTION); 00362 /* something is invalid, give em reorder for several seconds */ 00363 time(&rstart); 00364 while(time(NULL) < rstart + 10) { 00365 if (ast_waitfor(chan, -1) < 0) 00366 break; 00367 f = ast_read(chan); 00368 if (!f) 00369 break; 00370 ast_frfree(f); 00371 } 00372 ast_playtones_stop(chan); 00373 ast_module_user_remove(u); 00374 return -1; 00375 }
static int load_module | ( | void | ) | [static] |
Definition at line 388 of file app_disa.c.
References ast_register_application(), and disa_exec().
00389 { 00390 return ast_register_application(app, disa_exec, synopsis, descrip); 00391 }
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 377 of file app_disa.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00378 { 00379 int res; 00380 00381 res = ast_unregister_application(app); 00382 00383 ast_module_user_hangup_all(); 00384 00385 return res; 00386 }
char* app = "DISA" [static] |
Definition at line 52 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.