Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Enumerations | Functions | Variables
app_disa.c File Reference

DISA – Direct Inward System Access Application. More...

#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"
Include dependency graph for app_disa.c:

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)
 
struct ast_moduleAST_MODULE_SELF_SYM (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 = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "DISA"
 
static const struct ast_app_option app_opts [128] = { [ 'n' ] = { .flag = NOANSWER_FLAG }, [ 'p' ] = { .flag = POUND_TO_END_FLAG }, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

DISA – Direct Inward System Access Application.

Author
Jim Dixon jim@l.nosp@m.ambd.nosp@m.atel..nosp@m.com

Definition in file app_disa.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
NOANSWER_FLAG 
POUND_TO_END_FLAG 

Definition at line 121 of file app_disa.c.

121 {
122 NOANSWER_FLAG = (1 << 0),
123 POUND_TO_END_FLAG = (1 << 1),
124};
@ NOANSWER_FLAG
Definition app_disa.c:122
@ POUND_TO_END_FLAG
Definition app_disa.c:123

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 422 of file app_disa.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 422 of file app_disa.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 422 of file app_disa.c.

◆ disa_exec()

static int disa_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 149 of file app_disa.c.

150{
151 int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0;
152 int firstdigittimeout = (ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 20000);
153 int digittimeout = (ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 10000);
154 struct ast_flags flags;
155 char *tmp, exten[AST_MAX_EXTENSION] = "", acctcode[20]="";
156 char pwline[256];
157 char ourcidname[256],ourcidnum[256];
158 struct ast_frame *f;
159 struct timeval lastdigittime;
160 int res;
161 FILE *fp;
163 AST_APP_ARG(passcode);
164 AST_APP_ARG(context);
165 AST_APP_ARG(cid);
166 AST_APP_ARG(mailbox);
168 );
169
170 if (ast_strlen_zero(data)) {
171 ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
172 return -1;
173 }
174
175 ast_debug(1, "Digittimeout: %d\n", digittimeout);
176 ast_debug(1, "Responsetimeout: %d\n", firstdigittimeout);
177
178 tmp = ast_strdupa(data);
179
181
182 if (ast_strlen_zero(args.context))
183 args.context = "disa";
184 if (ast_strlen_zero(args.mailbox))
185 args.mailbox = "";
186 if (!ast_strlen_zero(args.options)) {
187 ast_app_parse_options(app_opts, &flags, NULL, args.options);
188 } else {
189 /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
191 }
192
193
194 ast_debug(1, "Mailbox: %s\n",args.mailbox);
195
196 if (!ast_test_flag(&flags, NOANSWER_FLAG)) {
197 if (ast_channel_state(chan) != AST_STATE_UP) {
198 /* answer */
199 ast_answer(chan);
200 }
201 } else special_noanswer = 1;
202
203 ast_debug(1, "Context: %s\n",args.context);
204
205 if (!strcasecmp(args.passcode, "no-password")) {
206 k |= 1; /* We have the password */
207 ast_debug(1, "DISA no-password login success\n");
208 }
209
210 lastdigittime = ast_tvnow();
211
212 play_dialtone(chan, args.mailbox);
213
215
216 for (;;) {
217 /* if outa time, give em reorder */
218 if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((k&2) ? digittimeout : firstdigittimeout)) {
219 ast_debug(1,"DISA %s entry timeout on chan %s\n",
220 ((k&1) ? "extension" : "password"),ast_channel_name(chan));
221 break;
222 }
223
224 if ((res = ast_waitfor(chan, -1)) < 0) {
225 ast_debug(1, "Waitfor returned %d\n", res);
226 continue;
227 }
228
229 if (!(f = ast_read(chan))) {
231 return -1;
232 }
233
235 if (f->data.uint32)
237 ast_frfree(f);
239 return -1;
240 }
241
242 /* If the frame coming in is not DTMF, just drop it and continue */
243 if (f->frametype != AST_FRAME_DTMF) {
244 ast_frfree(f);
245 continue;
246 }
247
248 j = f->subclass.integer; /* save digit */
249 ast_frfree(f);
250
251 if (!i) {
252 k |= 2; /* We have the first digit */
253 ast_playtones_stop(chan);
254 }
255
256 lastdigittime = ast_tvnow();
257
258 /* got a DTMF tone */
259 if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
260 if (!(k&1)) { /* if in password state */
261 if (j == '#') { /* end of password */
262 /* see if this is an integer */
263 if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */
264 fp = fopen(args.passcode,"r");
265 if (!fp) {
266 ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,ast_channel_name(chan));
268 return -1;
269 }
270 pwline[0] = 0;
271 while(fgets(pwline,sizeof(pwline) - 1,fp)) {
272 if (!pwline[0])
273 continue;
274 if (pwline[strlen(pwline) - 1] == '\n')
275 pwline[strlen(pwline) - 1] = 0;
276 if (!pwline[0])
277 continue;
278 /* skip comments */
279 if (pwline[0] == '#')
280 continue;
281 if (pwline[0] == ';')
282 continue;
283
285
286 ast_debug(1, "Mailbox: %s\n",args.mailbox);
287
288 /* password must be in valid format (numeric) */
289 if (sscanf(args.passcode,"%30d", &j) < 1)
290 continue;
291 /* if we got it */
292 if (!strcmp(exten,args.passcode)) {
293 if (ast_strlen_zero(args.context))
294 args.context = "disa";
295 if (ast_strlen_zero(args.mailbox))
296 args.mailbox = "";
297 break;
298 }
299 }
300 fclose(fp);
301 }
302 /* compare the two */
303 if (strcmp(exten,args.passcode)) {
304 ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",ast_channel_name(chan),exten);
305 goto reorder;
306
307 }
308 /* password good, set to dial state */
309 ast_debug(1,"DISA on chan %s password is good\n",ast_channel_name(chan));
310 play_dialtone(chan, args.mailbox);
311
312 k|=1; /* In number mode */
313 i = 0; /* re-set buffer pointer */
314 exten[sizeof(acctcode)] = 0;
315 ast_copy_string(acctcode, exten, sizeof(acctcode));
316 exten[0] = 0;
317 ast_debug(1,"Successful DISA log-in on chan %s\n", ast_channel_name(chan));
318 continue;
319 }
320 } else {
321 if (j == '#') { /* end of extension .. maybe */
322 if (i == 0
323 && (ast_matchmore_extension(chan, args.context, "#", 1,
324 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
325 || ast_exists_extension(chan, args.context, "#", 1,
326 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) ) {
327 /* Let the # be the part of, or the entire extension */
328 } else {
329 break;
330 }
331 }
332 }
333
334 exten[i++] = j; /* save digit */
335 exten[i] = 0;
336 if (!(k&1))
337 continue; /* if getting password, continue doing it */
338 /* if this exists */
339
340 /* user wants end of number, remove # */
341 if (ast_test_flag(&flags, POUND_TO_END_FLAG) && j == '#') {
342 exten[--i] = 0;
343 break;
344 }
345
346 if (ast_ignore_pattern(args.context, exten)) {
347 play_dialtone(chan, "");
348 did_ignore = 1;
349 } else
350 if (did_ignore) {
351 ast_playtones_stop(chan);
352 did_ignore = 0;
353 }
354
355 /* if can do some more, do it */
356 if (!ast_matchmore_extension(chan, args.context, exten, 1,
357 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
358 break;
359 }
360 }
361 }
362
364
365 if (k == 3) {
366 int recheck = 0;
367
368 if (!ast_exists_extension(chan, args.context, exten, 1,
369 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
370 pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
371 exten[0] = 'i';
372 exten[1] = '\0';
373 recheck = 1;
374 }
375 if (!recheck
376 || ast_exists_extension(chan, args.context, exten, 1,
377 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
378 ast_playtones_stop(chan);
379 /* We're authenticated and have a target extension */
380 if (!ast_strlen_zero(args.cid)) {
381 ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
382 ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
383 }
384
385 if (!ast_strlen_zero(acctcode)) {
386 ast_channel_lock(chan);
387 ast_channel_accountcode_set(chan, acctcode);
388 ast_channel_unlock(chan);
389 }
390
391 if (ast_pbx_exec_application(chan, "ResetCDR", special_noanswer ? "" : "e")) {
392 ast_log(AST_LOG_NOTICE, "ResetCDR application not found; CDR will not be reset\n");
393 }
394 ast_explicit_goto(chan, args.context, exten, 1);
395 return 0;
396 }
397 }
398
399 /* Received invalid, but no "i" extension exists in the given context */
400
401reorder:
402 /* Play congestion for a bit */
404 ast_safe_sleep(chan, 10*1000);
405
406 ast_playtones_stop(chan);
407
408 return -1;
409}
static const struct ast_app_option app_opts[128]
Definition app_disa.c:129
static void play_dialtone(struct ast_channel *chan, char *mailbox)
Definition app_disa.c:131
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition callerid.c:1292
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
Definition channel.c:11078
#define ast_channel_lock(chan)
Definition channel.h:2982
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition channel.c:3159
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4250
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition channel.c:7346
void ast_channel_set_flag(struct ast_channel *chan, unsigned int flag)
Set a flag on a channel.
Definition channel.c:11071
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
@ AST_FLAG_END_DTMF_ONLY
Definition channel.h:1027
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition channel.c:2803
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition channel.c:4270
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition channel.c:1560
#define ast_channel_unlock(chan)
Definition channel.h:2983
#define AST_MAX_EXTENSION
Definition channel.h:134
ast_channel_state
ast_channel states
@ AST_STATE_UP
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition main/app.c:3066
#define AST_FRAME_DTMF
#define ast_frfree(fr)
@ AST_FRAME_CONTROL
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LOG_NOTICE
#define LOG_WARNING
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition pbx.c:4196
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition pbx_app.c:501
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition pbx.c:6966
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition pbx.c:6900
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition pbx.c:4216
static struct @519 args
#define NULL
Definition resample.c:96
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Structure used to handle boolean flags.
Definition utils.h:220
unsigned int flags
Definition utils.h:221
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
int rtimeoutms
Definition pbx.h:217
int dtimeoutms
Definition pbx.h:216
Number structure.
static struct test_options options
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define AST_FLAGS_ALL
Definition utils.h:217

References app_opts, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_callerid_split(), ast_channel_caller(), ast_channel_clear_flag(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_set_flag(), ast_channel_unlock, ast_clear_flag, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_explicit_goto(), AST_FLAG_END_DTMF_ONLY, AST_FLAGS_ALL, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_ignore_pattern(), ast_indicate(), ast_log, AST_LOG_NOTICE, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_pbx_exec_application(), ast_playtones_stop(), ast_read(), ast_safe_sleep(), ast_set_callerid(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_channel::context, ast_frame::data, ast_pbx::dtimeoutms, ast_flags::flags, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NOANSWER_FLAG, NULL, options, pbx_builtin_setvar_helper(), play_dialtone(), POUND_TO_END_FLAG, ast_pbx::rtimeoutms, S_COR, ast_frame::subclass, and ast_frame::uint32.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 416 of file app_disa.c.

417{
420}
static const char app[]
Definition app_disa.c:119
static int disa_exec(struct ast_channel *chan, const char *data)
Definition app_disa.c:149
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition module.h:640

References app, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and disa_exec().

◆ play_dialtone()

static void play_dialtone ( struct ast_channel chan,
char *  mailbox 
)
static

Definition at line 131 of file app_disa.c.

132{
133 struct ast_tone_zone_sound *ts = NULL;
134
135 if (ast_app_has_voicemail(mailbox, NULL)) {
136 ts = ast_get_indication_tone(ast_channel_zone(chan), "dialrecall");
137 } else {
138 ts = ast_get_indication_tone(ast_channel_zone(chan), "dial");
139 }
140
141 if (ts) {
142 ast_playtones_start(chan, 0, ts->data, 0);
144 } else {
145 ast_tonepair_start(chan, 350, 440, 0, 0);
146 }
147}
int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
Definition channel.c:7594
struct ast_tone_zone * ast_channel_zone(const struct ast_channel *chan)
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX"....
Definition main/app.c:582
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Description of a tone.
Definition indications.h:35
const char * data
Description of a tone.
Definition indications.h:52

References ast_app_has_voicemail(), ast_channel_zone(), ast_get_indication_tone(), ast_playtones_start(), ast_tone_zone_sound_unref(), ast_tonepair_start(), ast_tone_zone_sound::data, and NULL.

Referenced by disa_exec().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 411 of file app_disa.c.

412{
414}
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "DISA (Direct Inward System Access) Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 422 of file app_disa.c.

◆ app

const char app[] = "DISA"
static

Definition at line 119 of file app_disa.c.

Referenced by load_module(), and unload_module().

◆ app_opts

const struct ast_app_option app_opts[128] = { [ 'n' ] = { .flag = NOANSWER_FLAG }, [ 'p' ] = { .flag = POUND_TO_END_FLAG }, }
static
Examples
app_skel.c.

Definition at line 129 of file app_disa.c.

Referenced by app_exec(), and disa_exec().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 422 of file app_disa.c.