Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
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"

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 118 of file app_disa.c.

118  {
119  NOANSWER_FLAG = (1 << 0),
120  POUND_TO_END_FLAG = (1 << 1),
121 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 423 of file app_disa.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 423 of file app_disa.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 423 of file app_disa.c.

◆ disa_exec()

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

Definition at line 146 of file app_disa.c.

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_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(), context, ast_frame::data, ast_pbx::dtimeoutms, exten, firstdigittimeout, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, mailbox, NOANSWER_FLAG, NULL, options, pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), play_dialtone(), POUND_TO_END_FLAG, ast_pbx::rtimeoutms, S_COR, ast_frame::subclass, tmp(), and ast_frame::uint32.

Referenced by load_module().

147 {
148  int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0;
149  int firstdigittimeout = (ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 20000);
150  int digittimeout = (ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 10000);
151  struct ast_flags flags;
152  char *tmp, exten[AST_MAX_EXTENSION] = "", acctcode[20]="";
153  char pwline[256];
154  char ourcidname[256],ourcidnum[256];
155  struct ast_frame *f;
156  struct timeval lastdigittime;
157  int res;
158  FILE *fp;
160  AST_APP_ARG(passcode);
162  AST_APP_ARG(cid);
165  );
166 
167  if (ast_strlen_zero(data)) {
168  ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
169  return -1;
170  }
171 
172  ast_debug(1, "Digittimeout: %d\n", digittimeout);
173  ast_debug(1, "Responsetimeout: %d\n", firstdigittimeout);
174 
175  tmp = ast_strdupa(data);
176 
178 
179  if (ast_strlen_zero(args.context))
180  args.context = "disa";
181  if (ast_strlen_zero(args.mailbox))
182  args.mailbox = "";
183  if (!ast_strlen_zero(args.options)) {
184  ast_app_parse_options(app_opts, &flags, NULL, args.options);
185  } else {
186  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
187  ast_clear_flag(&flags, AST_FLAGS_ALL);
188  }
189 
190 
191  ast_debug(1, "Mailbox: %s\n",args.mailbox);
192 
193  if (!ast_test_flag(&flags, NOANSWER_FLAG)) {
194  if (ast_channel_state(chan) != AST_STATE_UP) {
195  /* answer */
196  ast_answer(chan);
197  }
198  } else special_noanswer = 1;
199 
200  ast_debug(1, "Context: %s\n",args.context);
201 
202  if (!strcasecmp(args.passcode, "no-password")) {
203  k |= 1; /* We have the password */
204  ast_debug(1, "DISA no-password login success\n");
205  }
206 
207  lastdigittime = ast_tvnow();
208 
209  play_dialtone(chan, args.mailbox);
210 
212 
213  for (;;) {
214  /* if outa time, give em reorder */
215  if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((k&2) ? digittimeout : firstdigittimeout)) {
216  ast_debug(1,"DISA %s entry timeout on chan %s\n",
217  ((k&1) ? "extension" : "password"),ast_channel_name(chan));
218  break;
219  }
220 
221  if ((res = ast_waitfor(chan, -1)) < 0) {
222  ast_debug(1, "Waitfor returned %d\n", res);
223  continue;
224  }
225 
226  if (!(f = ast_read(chan))) {
228  return -1;
229  }
230 
232  if (f->data.uint32)
234  ast_frfree(f);
236  return -1;
237  }
238 
239  /* If the frame coming in is not DTMF, just drop it and continue */
240  if (f->frametype != AST_FRAME_DTMF) {
241  ast_frfree(f);
242  continue;
243  }
244 
245  j = f->subclass.integer; /* save digit */
246  ast_frfree(f);
247 
248  if (!i) {
249  k |= 2; /* We have the first digit */
250  ast_playtones_stop(chan);
251  }
252 
253  lastdigittime = ast_tvnow();
254 
255  /* got a DTMF tone */
256  if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
257  if (!(k&1)) { /* if in password state */
258  if (j == '#') { /* end of password */
259  /* see if this is an integer */
260  if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */
261  fp = fopen(args.passcode,"r");
262  if (!fp) {
263  ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,ast_channel_name(chan));
265  return -1;
266  }
267  pwline[0] = 0;
268  while(fgets(pwline,sizeof(pwline) - 1,fp)) {
269  if (!pwline[0])
270  continue;
271  if (pwline[strlen(pwline) - 1] == '\n')
272  pwline[strlen(pwline) - 1] = 0;
273  if (!pwline[0])
274  continue;
275  /* skip comments */
276  if (pwline[0] == '#')
277  continue;
278  if (pwline[0] == ';')
279  continue;
280 
281  AST_STANDARD_APP_ARGS(args, pwline);
282 
283  ast_debug(1, "Mailbox: %s\n",args.mailbox);
284 
285  /* password must be in valid format (numeric) */
286  if (sscanf(args.passcode,"%30d", &j) < 1)
287  continue;
288  /* if we got it */
289  if (!strcmp(exten,args.passcode)) {
290  if (ast_strlen_zero(args.context))
291  args.context = "disa";
292  if (ast_strlen_zero(args.mailbox))
293  args.mailbox = "";
294  break;
295  }
296  }
297  fclose(fp);
298  }
299  /* compare the two */
300  if (strcmp(exten,args.passcode)) {
301  ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",ast_channel_name(chan),exten);
302  goto reorder;
303 
304  }
305  /* password good, set to dial state */
306  ast_debug(1,"DISA on chan %s password is good\n",ast_channel_name(chan));
307  play_dialtone(chan, args.mailbox);
308 
309  k|=1; /* In number mode */
310  i = 0; /* re-set buffer pointer */
311  exten[sizeof(acctcode)] = 0;
312  ast_copy_string(acctcode, exten, sizeof(acctcode));
313  exten[0] = 0;
314  ast_debug(1,"Successful DISA log-in on chan %s\n", ast_channel_name(chan));
315  continue;
316  }
317  } else {
318  if (j == '#') { /* end of extension .. maybe */
319  if (i == 0
320  && (ast_matchmore_extension(chan, args.context, "#", 1,
321  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
322  || ast_exists_extension(chan, args.context, "#", 1,
323  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) ) {
324  /* Let the # be the part of, or the entire extension */
325  } else {
326  break;
327  }
328  }
329  }
330 
331  exten[i++] = j; /* save digit */
332  exten[i] = 0;
333  if (!(k&1))
334  continue; /* if getting password, continue doing it */
335  /* if this exists */
336 
337  /* user wants end of number, remove # */
338  if (ast_test_flag(&flags, POUND_TO_END_FLAG) && j == '#') {
339  exten[--i] = 0;
340  break;
341  }
342 
343  if (ast_ignore_pattern(args.context, exten)) {
344  play_dialtone(chan, "");
345  did_ignore = 1;
346  } else
347  if (did_ignore) {
348  ast_playtones_stop(chan);
349  did_ignore = 0;
350  }
351 
352  /* if can do some more, do it */
353  if (!ast_matchmore_extension(chan, args.context, exten, 1,
354  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
355  break;
356  }
357  }
358  }
359 
361 
362  if (k == 3) {
363  int recheck = 0;
364  struct ast_app *app_reset_cdr;
365 
366  if (!ast_exists_extension(chan, args.context, exten, 1,
367  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
368  pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
369  exten[0] = 'i';
370  exten[1] = '\0';
371  recheck = 1;
372  }
373  if (!recheck
374  || ast_exists_extension(chan, args.context, exten, 1,
375  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
376  ast_playtones_stop(chan);
377  /* We're authenticated and have a target extension */
378  if (!ast_strlen_zero(args.cid)) {
379  ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
380  ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
381  }
382 
383  if (!ast_strlen_zero(acctcode)) {
384  ast_channel_lock(chan);
385  ast_channel_accountcode_set(chan, acctcode);
386  ast_channel_unlock(chan);
387  }
388 
389  app_reset_cdr = pbx_findapp("ResetCDR");
390  if (app_reset_cdr) {
391  pbx_exec(chan, app_reset_cdr, special_noanswer ? "" : "e");
392  } else {
393  ast_log(AST_LOG_NOTICE, "ResetCDR application not found; CDR will not be reset\n");
394  }
395  ast_explicit_goto(chan, args.context, exten, 1);
396  return 0;
397  }
398  }
399 
400  /* Received invalid, but no "i" extension exists in the given context */
401 
402 reorder:
403  /* Play congestion for a bit */
405  ast_safe_sleep(chan, 10*1000);
406 
407  ast_playtones_stop(chan);
408 
409  return -1;
410 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1554
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:7273
#define ast_channel_lock(chan)
Definition: channel.h:2837
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:4190
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int firstdigittimeout
Definition: chan_mgcp.c:214
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
static void play_dialtone(struct ast_channel *chan, char *mailbox)
Definition: app_disa.c:128
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4271
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static const struct ast_app_option app_opts[128]
Definition: app_disa.c:126
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Definition: channel.c:11063
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4251
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6912
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6978
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
const char * args
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
Number structure.
Definition: app_followme.c:154
union ast_frame::@255 data
#define AST_LOG_NOTICE
Definition: logger.h:268
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#define AST_MAX_EXTENSION
Definition: channel.h:135
#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:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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:4170
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:2829
void ast_channel_set_flag(struct ast_channel *chan, unsigned int flag)
Set a flag on a channel.
Definition: channel.c:11056
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
#define AST_FLAGS_ALL
Definition: utils.h:196
Structure used to handle boolean flags.
Definition: utils.h:199
#define ast_clear_flag(p, flag)
Definition: utils.h:77
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_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3137
int dtimeoutms
Definition: pbx.h:212
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
ast_app: A registered application
Definition: pbx_app.c:45
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2780
Data structure associated with a single frame of data.
enum ast_frame_type frametype
static struct test_options options
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.
int rtimeoutms
Definition: pbx.h:213

◆ load_module()

static int load_module ( void  )
static

Definition at line 417 of file app_disa.c.

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

418 {
421 }
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static const char app[]
Definition: app_disa.c:116
static int disa_exec(struct ast_channel *chan, const char *data)
Definition: app_disa.c:146
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ play_dialtone()

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

Definition at line 128 of file app_disa.c.

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().

129 {
130  struct ast_tone_zone_sound *ts = NULL;
131 
133  ts = ast_get_indication_tone(ast_channel_zone(chan), "dialrecall");
134  } else {
135  ts = ast_get_indication_tone(ast_channel_zone(chan), "dial");
136  }
137 
138  if (ts) {
139  ast_playtones_start(chan, 0, ts->data, 0);
140  ts = ast_tone_zone_sound_unref(ts);
141  } else {
142  ast_tonepair_start(chan, 350, 440, 0, 0);
143  }
144 }
struct ast_tone_zone * ast_channel_zone(const struct ast_channel *chan)
#define NULL
Definition: resample.c:96
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
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
Description of a tone.
Definition: indications.h:35
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:455
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". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
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
int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
Definition: channel.c:7521
const char * data
Description of a tone.
Definition: indications.h:52

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 412 of file app_disa.c.

References app, and ast_unregister_application().

413 {
415 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static const char app[]
Definition: app_disa.c:116

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 423 of file app_disa.c.

◆ app

const char app[] = "DISA"
static

Definition at line 116 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 126 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 423 of file app_disa.c.