Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 = "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 = 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);
165 AST_APP_ARG(cid);
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:11039
#define ast_channel_lock(chan)
Definition: channel.h:2972
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4214
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:7307
void ast_channel_set_flag(struct ast_channel *chan, unsigned int flag)
Set a flag on a channel.
Definition: channel.c:11032
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1027
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4234
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1541
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define AST_MAX_EXTENSION
Definition: channel.h:134
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#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.
Definition: indications.c:393
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:4190
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:6960
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6894
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:4210
#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:199
unsigned int flags
Definition: utils.h:200
Data structure associated with a single frame of data.
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
int rtimeoutms
Definition: pbx.h:217
int dtimeoutms
Definition: pbx.h:216
Number structure.
Definition: app_followme.c:157
const char * args
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:63
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define AST_FLAGS_ALL
Definition: utils.h:196

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(), voicemailpwcheck::context, ast_frame::data, ast_pbx::dtimeoutms, ast_flags::flags, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, voicemailpwcheck::mailbox, 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
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:7555
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.
Definition: indications.h:227
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:461
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, voicemailpwcheck::mailbox, 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 = "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 = 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

Definition at line 129 of file app_disa.c.

Referenced by 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.