#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "asterisk.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 dependency graph for app_disa.c:
Go to the source code of this file.
Functions | |
char * | description (void) |
Provides a description of the module. | |
static int | disa_exec (struct ast_channel *chan, void *data) |
char * | key (void) |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static void | play_dialtone (struct ast_channel *chan, char *mailbox) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | app = "DISA" |
static char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
static char * | synopsis = "DISA (Direct Inward System Access)" |
static char * | tdesc = "DISA (Direct Inward System Access) Application" |
Definition in file app_disa.c.
|
Provides a description of the module.
Definition at line 397 of file app_disa.c. 00398 { 00399 return tdesc; 00400 }
|
|
Definition at line 115 of file app_disa.c. References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_FORMAT_ULAW, ast_log(), AST_MAX_EXTENSION, ast_set_read_format(), ast_set_write_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), context, ast_pbx::dtimeout, exten, firstdigittimeout, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_ERROR, LOG_WARNING, mailbox, ast_channel::name, ast_channel::pbx, play_dialtone(), and ast_pbx::rtimeout. Referenced by load_module(). 00116 { 00117 int i,j,k,x,did_ignore; 00118 int firstdigittimeout = 20000; 00119 int digittimeout = 10000; 00120 struct localuser *u; 00121 char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]=""; 00122 char pwline[256]; 00123 char ourcidname[256],ourcidnum[256]; 00124 struct ast_frame *f; 00125 struct timeval lastdigittime; 00126 int res; 00127 time_t rstart; 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 ); 00135 00136 if (ast_strlen_zero(data)) { 00137 ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n"); 00138 return -1; 00139 } 00140 00141 LOCAL_USER_ADD(u); 00142 00143 if (chan->pbx) { 00144 firstdigittimeout = chan->pbx->rtimeout*1000; 00145 digittimeout = chan->pbx->dtimeout*1000; 00146 } 00147 00148 if (ast_set_write_format(chan,AST_FORMAT_ULAW)) { 00149 ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name); 00150 LOCAL_USER_REMOVE(u); 00151 return -1; 00152 } 00153 if (ast_set_read_format(chan,AST_FORMAT_ULAW)) { 00154 ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name); 00155 LOCAL_USER_REMOVE(u); 00156 return -1; 00157 } 00158 00159 ast_log(LOG_DEBUG, "Digittimeout: %d\n", digittimeout); 00160 ast_log(LOG_DEBUG, "Responsetimeout: %d\n", firstdigittimeout); 00161 00162 tmp = ast_strdupa(data); 00163 if (!tmp) { 00164 ast_log(LOG_ERROR, "Out of memory\n"); 00165 LOCAL_USER_REMOVE(u); 00166 return -1; 00167 } 00168 00169 AST_STANDARD_APP_ARGS(args, tmp); 00170 00171 if (ast_strlen_zero(args.context)) 00172 args.context = "disa"; 00173 if (ast_strlen_zero(args.mailbox)) 00174 args.mailbox = ""; 00175 00176 ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox); 00177 00178 if (chan->_state != AST_STATE_UP) { 00179 /* answer */ 00180 ast_answer(chan); 00181 } 00182 i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */ 00183 did_ignore = 0; 00184 exten[0] = 0; 00185 acctcode[0] = 0; 00186 /* can we access DISA without password? */ 00187 00188 ast_log(LOG_DEBUG, "Context: %s\n",args.context); 00189 00190 if (!strcasecmp(args.passcode, "no-password")) { 00191 k |= 1; /* We have the password */ 00192 ast_log(LOG_DEBUG, "DISA no-password login success\n"); 00193 } 00194 lastdigittime = ast_tvnow(); 00195 00196 play_dialtone(chan, args.mailbox); 00197 00198 for (;;) { 00199 /* if outa time, give em reorder */ 00200 if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > 00201 ((k&2) ? digittimeout : firstdigittimeout)) 00202 { 00203 ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n", 00204 ((k&1) ? "extension" : "password"),chan->name); 00205 break; 00206 } 00207 if ((res = ast_waitfor(chan, -1) < 0)) { 00208 ast_log(LOG_DEBUG, "Waitfor returned %d\n", res); 00209 continue; 00210 } 00211 00212 f = ast_read(chan); 00213 if (f == NULL) 00214 { 00215 LOCAL_USER_REMOVE(u); 00216 return -1; 00217 } 00218 if ((f->frametype == AST_FRAME_CONTROL) && 00219 (f->subclass == AST_CONTROL_HANGUP)) 00220 { 00221 ast_frfree(f); 00222 LOCAL_USER_REMOVE(u); 00223 return -1; 00224 } 00225 if (f->frametype == AST_FRAME_VOICE) { 00226 ast_frfree(f); 00227 continue; 00228 } 00229 /* if not DTMF, just do it again */ 00230 if (f->frametype != AST_FRAME_DTMF) 00231 { 00232 ast_frfree(f); 00233 continue; 00234 } 00235 00236 j = f->subclass; /* save digit */ 00237 ast_frfree(f); 00238 if (i == 0) 00239 { 00240 k|=2; /* We have the first digit */ 00241 ast_playtones_stop(chan); 00242 } 00243 lastdigittime = ast_tvnow(); 00244 /* got a DTMF tone */ 00245 if (i < AST_MAX_EXTENSION) /* if still valid number of digits */ 00246 { 00247 if (!(k&1)) /* if in password state */ 00248 { 00249 if (j == '#') /* end of password */ 00250 { 00251 /* see if this is an integer */ 00252 if (sscanf(args.passcode,"%d",&j) < 1) 00253 { /* nope, it must be a filename */ 00254 fp = fopen(args.passcode,"r"); 00255 if (!fp) 00256 { 00257 ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name); 00258 LOCAL_USER_REMOVE(u); 00259 return -1; 00260 } 00261 pwline[0] = 0; 00262 while(fgets(pwline,sizeof(pwline) - 1,fp)) 00263 { 00264 if (!pwline[0]) continue; 00265 if (pwline[strlen(pwline) - 1] == '\n') 00266 pwline[strlen(pwline) - 1] = 0; 00267 if (!pwline[0]) continue; 00268 /* skip comments */ 00269 if (pwline[0] == '#') continue; 00270 if (pwline[0] == ';') continue; 00271 00272 AST_STANDARD_APP_ARGS(args, pwline); 00273 00274 ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox); 00275 00276 /* password must be in valid format (numeric) */ 00277 if (sscanf(args.passcode,"%d",&j) < 1) continue; 00278 /* if we got it */ 00279 if (!strcmp(exten,args.passcode)) { 00280 if (ast_strlen_zero(args.context)) 00281 args.context = "disa"; 00282 if (ast_strlen_zero(args.mailbox)) 00283 args.mailbox = ""; 00284 break; 00285 } 00286 } 00287 fclose(fp); 00288 } 00289 /* compare the two */ 00290 if (strcmp(exten,args.passcode)) 00291 { 00292 ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten); 00293 goto reorder; 00294 00295 } 00296 /* password good, set to dial state */ 00297 ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name); 00298 play_dialtone(chan, args.mailbox); 00299 00300 k|=1; /* In number mode */ 00301 i = 0; /* re-set buffer pointer */ 00302 exten[sizeof(acctcode)] = 0; 00303 ast_copy_string(acctcode, exten, sizeof(acctcode)); 00304 exten[0] = 0; 00305 ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name); 00306 continue; 00307 } 00308 } 00309 00310 exten[i++] = j; /* save digit */ 00311 exten[i] = 0; 00312 if (!(k&1)) continue; /* if getting password, continue doing it */ 00313 /* if this exists */ 00314 00315 if (ast_ignore_pattern(args.context, exten)) { 00316 play_dialtone(chan, ""); 00317 did_ignore = 1; 00318 } else 00319 if (did_ignore) { 00320 ast_playtones_stop(chan); 00321 did_ignore = 0; 00322 } 00323 00324 /* if can do some more, do it */ 00325 if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) { 00326 break; 00327 } 00328 } 00329 } 00330 00331 if (k == 3) { 00332 int recheck = 0; 00333 struct ast_flags flags = { AST_CDR_FLAG_POSTED }; 00334 00335 if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00336 pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten); 00337 exten[0] = 'i'; 00338 exten[1] = '\0'; 00339 recheck = 1; 00340 } 00341 if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) { 00342 ast_playtones_stop(chan); 00343 /* We're authenticated and have a target extension */ 00344 if (!ast_strlen_zero(args.cid)) 00345 { 00346 ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum)); 00347 ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum); 00348 } 00349 00350 if (!ast_strlen_zero(acctcode)) 00351 ast_copy_string(chan->accountcode, acctcode, sizeof(chan->accountcode)); 00352 00353 ast_cdr_reset(chan->cdr, &flags); 00354 ast_explicit_goto(chan, args.context, exten, 1); 00355 LOCAL_USER_REMOVE(u); 00356 return 0; 00357 } 00358 } 00359 00360 /* Received invalid, but no "i" extension exists in the given context */ 00361 00362 reorder: 00363 00364 ast_indicate(chan,AST_CONTROL_CONGESTION); 00365 /* something is invalid, give em reorder for several seconds */ 00366 time(&rstart); 00367 while(time(NULL) < rstart + 10) 00368 { 00369 if (ast_waitfor(chan, -1) < 0) 00370 break; 00371 f = ast_read(chan); 00372 if (!f) 00373 break; 00374 ast_frfree(f); 00375 } 00376 ast_playtones_stop(chan); 00377 LOCAL_USER_REMOVE(u); 00378 return -1; 00379 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 409 of file app_disa.c. References ASTERISK_GPL_KEY. 00410 { 00411 return ASTERISK_GPL_KEY; 00412 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 392 of file app_disa.c. References ast_register_application(), and disa_exec(). 00393 { 00394 return ast_register_application(app, disa_exec, synopsis, descrip); 00395 }
|
|
Definition at line 102 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(). 00103 { 00104 const struct tone_zone_sound *ts = NULL; 00105 if(ast_app_has_voicemail(mailbox, NULL)) 00106 ts = ast_get_indication_tone(chan->zone, "dialrecall"); 00107 else 00108 ts = ast_get_indication_tone(chan->zone, "dial"); 00109 if (ts) 00110 ast_playtones_start(chan, 0, ts->data, 0); 00111 else 00112 ast_tonepair_start(chan, 350, 440, 0, 0); 00113 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 381 of file app_disa.c. References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS. 00382 { 00383 int res; 00384 00385 res = ast_unregister_application(app); 00386 00387 STANDARD_HANGUP_LOCALUSERS; 00388 00389 return res; 00390 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 402 of file app_disa.c. References STANDARD_USECOUNT. 00403 { 00404 int res; 00405 STANDARD_USECOUNT(res); 00406 return res; 00407 }
|
|
Definition at line 53 of file app_disa.c. |
|
Definition at line 57 of file app_disa.c. |
|
Definition at line 100 of file app_disa.c. |
|
Definition at line 98 of file app_disa.c. |
|
Definition at line 55 of file app_disa.c. |
|
Definition at line 51 of file app_disa.c. |