Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


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)
 
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static const char app [] = "DISA"
 
static struct ast_app_option app_opts [128] = { [ 'n' ] = { .flag = NOANSWER_FLAG }, [ 'p' ] = { .flag = POUND_TO_END_FLAG }, }
 
static 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
Enumerator
NOANSWER_FLAG 
POUND_TO_END_FLAG 

Definition at line 119 of file app_disa.c.

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

Function Documentation

static void __reg_module ( void  )
static

Definition at line 417 of file app_disa.c.

static void __unreg_module ( void  )
static

Definition at line 417 of file app_disa.c.

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

Definition at line 147 of file app_disa.c.

References ast_channel::_state, accountcode, app_opts, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_callerid_split(), AST_CDR_FLAG_POSTED, ast_cdr_reset(), 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_matchmore_extension(), AST_MAX_EXTENSION, ast_playtones_stop(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_channel::caller, ast_channel::cdr, context, ast_frame::data, ast_pbx::dtimeoutms, exten, f, firstdigittimeout, ast_flags::flags, ast_frame::frametype, ast_channel::hangupcause, ast_party_caller::id, ast_frame_subclass::integer, LOG_WARNING, mailbox, ast_channel::name, NOANSWER_FLAG, ast_party_id::number, ast_channel::pbx, pbx_builtin_setvar_helper(), play_dialtone(), POUND_TO_END_FLAG, ast_pbx::rtimeoutms, S_COR, ast_party_number::str, ast_frame::subclass, ast_frame::uint32, and ast_party_number::valid.

Referenced by load_module().

148 {
149  int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0;
150  int firstdigittimeout = (chan->pbx ? chan->pbx->rtimeoutms : 20000);
151  int digittimeout = (chan->pbx ? chan->pbx->dtimeoutms : 10000);
152  struct ast_flags flags;
153  char *tmp, exten[AST_MAX_EXTENSION] = "", acctcode[20]="";
154  char pwline[256];
155  char ourcidname[256],ourcidnum[256];
156  struct ast_frame *f;
157  struct timeval lastdigittime;
158  int res;
159  FILE *fp;
161  AST_APP_ARG(passcode);
163  AST_APP_ARG(cid);
165  AST_APP_ARG(options);
166  );
167 
168  if (ast_strlen_zero(data)) {
169  ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
170  return -1;
171  }
172 
173  ast_debug(1, "Digittimeout: %d\n", digittimeout);
174  ast_debug(1, "Responsetimeout: %d\n", firstdigittimeout);
175 
176  tmp = ast_strdupa(data);
177 
179 
180  if (ast_strlen_zero(args.context))
181  args.context = "disa";
182  if (ast_strlen_zero(args.mailbox))
183  args.mailbox = "";
184  if (!ast_strlen_zero(args.options)) {
185  ast_app_parse_options(app_opts, &flags, NULL, args.options);
186  } else {
187  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
188  ast_clear_flag(&flags, AST_FLAGS_ALL);
189  }
190 
191 
192  ast_debug(1, "Mailbox: %s\n",args.mailbox);
193 
194  if (!ast_test_flag(&flags, NOANSWER_FLAG)) {
195  if (chan->_state != AST_STATE_UP) {
196  /* answer */
197  ast_answer(chan);
198  }
199  } else special_noanswer = 1;
200 
201  ast_debug(1, "Context: %s\n",args.context);
202 
203  if (!strcasecmp(args.passcode, "no-password")) {
204  k |= 1; /* We have the password */
205  ast_debug(1, "DISA no-password login success\n");
206  }
207 
208  lastdigittime = ast_tvnow();
209 
210  play_dialtone(chan, args.mailbox);
211 
213 
214  for (;;) {
215  /* if outa time, give em reorder */
216  if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((k&2) ? digittimeout : firstdigittimeout)) {
217  ast_debug(1,"DISA %s entry timeout on chan %s\n",
218  ((k&1) ? "extension" : "password"),chan->name);
219  break;
220  }
221 
222  if ((res = ast_waitfor(chan, -1) < 0)) {
223  ast_debug(1, "Waitfor returned %d\n", res);
224  continue;
225  }
226 
227  if (!(f = ast_read(chan))) {
229  return -1;
230  }
231 
233  if (f->data.uint32)
234  chan->hangupcause = f->data.uint32;
235  ast_frfree(f);
237  return -1;
238  }
239 
240  /* If the frame coming in is not DTMF, just drop it and continue */
241  if (f->frametype != AST_FRAME_DTMF) {
242  ast_frfree(f);
243  continue;
244  }
245 
246  j = f->subclass.integer; /* save digit */
247  ast_frfree(f);
248 
249  if (!i) {
250  k |= 2; /* We have the first digit */
251  ast_playtones_stop(chan);
252  }
253 
254  lastdigittime = ast_tvnow();
255 
256  /* got a DTMF tone */
257  if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
258  if (!(k&1)) { /* if in password state */
259  if (j == '#') { /* end of password */
260  /* see if this is an integer */
261  if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */
262  fp = fopen(args.passcode,"r");
263  if (!fp) {
264  ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name);
266  return -1;
267  }
268  pwline[0] = 0;
269  while(fgets(pwline,sizeof(pwline) - 1,fp)) {
270  if (!pwline[0])
271  continue;
272  if (pwline[strlen(pwline) - 1] == '\n')
273  pwline[strlen(pwline) - 1] = 0;
274  if (!pwline[0])
275  continue;
276  /* skip comments */
277  if (pwline[0] == '#')
278  continue;
279  if (pwline[0] == ';')
280  continue;
281 
282  AST_STANDARD_APP_ARGS(args, pwline);
283 
284  ast_debug(1, "Mailbox: %s\n",args.mailbox);
285 
286  /* password must be in valid format (numeric) */
287  if (sscanf(args.passcode,"%30d", &j) < 1)
288  continue;
289  /* if we got it */
290  if (!strcmp(exten,args.passcode)) {
291  if (ast_strlen_zero(args.context))
292  args.context = "disa";
293  if (ast_strlen_zero(args.mailbox))
294  args.mailbox = "";
295  break;
296  }
297  }
298  fclose(fp);
299  }
300  /* compare the two */
301  if (strcmp(exten,args.passcode)) {
302  ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
303  goto reorder;
304 
305  }
306  /* password good, set to dial state */
307  ast_debug(1,"DISA on chan %s password is good\n",chan->name);
308  play_dialtone(chan, args.mailbox);
309 
310  k|=1; /* In number mode */
311  i = 0; /* re-set buffer pointer */
312  exten[sizeof(acctcode)] = 0;
313  ast_copy_string(acctcode, exten, sizeof(acctcode));
314  exten[0] = 0;
315  ast_debug(1,"Successful DISA log-in on chan %s\n", chan->name);
316  continue;
317  }
318  } else {
319  if (j == '#') { /* end of extension .. maybe */
320  if (i == 0
321  && (ast_matchmore_extension(chan, args.context, "#", 1,
322  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
323  || ast_exists_extension(chan, args.context, "#", 1,
324  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) ) {
325  /* Let the # be the part of, or the entire extension */
326  } else {
327  break;
328  }
329  }
330  }
331 
332  exten[i++] = j; /* save digit */
333  exten[i] = 0;
334  if (!(k&1))
335  continue; /* if getting password, continue doing it */
336  /* if this exists */
337 
338  /* user wants end of number, remove # */
339  if (ast_test_flag(&flags, POUND_TO_END_FLAG) && j == '#') {
340  exten[--i] = 0;
341  break;
342  }
343 
344  if (ast_ignore_pattern(args.context, exten)) {
345  play_dialtone(chan, "");
346  did_ignore = 1;
347  } else
348  if (did_ignore) {
349  ast_playtones_stop(chan);
350  did_ignore = 0;
351  }
352 
353  /* if can do some more, do it */
354  if (!ast_matchmore_extension(chan, args.context, exten, 1,
355  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
356  break;
357  }
358  }
359  }
360 
362 
363  if (k == 3) {
364  int recheck = 0;
365  struct ast_flags cdr_flags = { AST_CDR_FLAG_POSTED };
366 
367  if (!ast_exists_extension(chan, args.context, exten, 1,
368  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
369  pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
370  exten[0] = 'i';
371  exten[1] = '\0';
372  recheck = 1;
373  }
374  if (!recheck
375  || ast_exists_extension(chan, args.context, exten, 1,
376  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
377  ast_playtones_stop(chan);
378  /* We're authenticated and have a target extension */
379  if (!ast_strlen_zero(args.cid)) {
380  ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
381  ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
382  }
383 
384  if (!ast_strlen_zero(acctcode))
385  ast_string_field_set(chan, accountcode, acctcode);
386 
387  if (special_noanswer) cdr_flags.flags = 0;
388  ast_cdr_reset(chan->cdr, &cdr_flags);
389  ast_explicit_goto(chan, args.context, exten, 1);
390  return 0;
391  }
392  }
393 
394  /* Received invalid, but no "i" extension exists in the given context */
395 
396 reorder:
397  /* Play congestion for a bit */
399  ast_safe_sleep(chan, 10*1000);
400 
401  ast_playtones_stop(chan);
402 
403  return -1;
404 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
union ast_frame_subclass subclass
Definition: frame.h:146
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
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:7051
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:5420
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1093
static void play_dialtone(struct ast_channel *chan, char *mailbox)
Definition: app_disa.c:129
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
Definition: cdr.c:1149
#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:4393
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
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: app.c:2101
#define AST_FRAME_DTMF
Definition: frame.h:128
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:8650
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
struct ast_cdr * cdr
Definition: channel.h:766
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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:83
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:5400
static int firstdigittimeout
Wait up to 16 seconds for first digit (FXO logic)
Definition: chan_dahdi.c:449
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_app_option app_opts[128]
Definition: app_disa.c:127
#define AST_FLAGS_ALL
Definition: utils.h:196
static struct ast_format f[]
Definition: format_g726.c:181
Structure used to handle boolean flags.
Definition: utils.h:200
#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...
Definition: pbx.c:10546
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
int dtimeoutms
Definition: pbx.h:180
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
uint32_t uint32
Definition: frame.h:160
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
union ast_frame::@172 data
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
struct ast_pbx * pbx
Definition: channel.h:761
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
int rtimeoutms
Definition: pbx.h:181
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int load_module ( void  )
static

Definition at line 411 of file app_disa.c.

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

412 {
415 }
static const char app[]
Definition: app_disa.c:117
static int disa_exec(struct ast_channel *chan, const char *data)
Definition: app_disa.c:147
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static void play_dialtone ( struct ast_channel chan,
char *  mailbox 
)
static

Definition at line 129 of file app_disa.c.

References ast_app_has_voicemail(), ast_get_indication_tone(), ast_playtones_start(), ast_tone_zone_sound_unref(), ast_tonepair_start(), ast_tone_zone_sound::data, and ast_channel::zone.

Referenced by disa_exec().

130 {
131  struct ast_tone_zone_sound *ts = NULL;
132 
133  if (ast_app_has_voicemail(mailbox, NULL)) {
134  ts = ast_get_indication_tone(chan->zone, "dialrecall");
135  } else {
136  ts = ast_get_indication_tone(chan->zone, "dial");
137  }
138 
139  if (ts) {
140  ast_playtones_start(chan, 0, ts->data, 0);
141  ts = ast_tone_zone_sound_unref(ts);
142  } else {
143  ast_tonepair_start(chan, 350, 440, 0, 0);
144  }
145 }
struct ast_tone_zone * zone
Definition: channel.h:767
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to &quot;INBOX&quot;. If folder is &quot;INBOX&quot;, includes the number of messages in the &quot;Urgent&quot; folder.
Definition: app.c:421
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:226
Description of a tone.
Definition: indications.h:36
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:473
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:319
int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
Definition: channel.c:7951
const char * data
Description of a tone.
Definition: indications.h:53
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static int unload_module ( void  )
static

Definition at line 406 of file app_disa.c.

References ast_unregister_application().

407 {
409 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static const char app[]
Definition: app_disa.c:117

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 417 of file app_disa.c.

const char app[] = "DISA"
static

Definition at line 117 of file app_disa.c.

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

Definition at line 127 of file app_disa.c.

Referenced by disa_exec().

Definition at line 417 of file app_disa.c.