44#include <netinet/in.h>
56static const char app[] =
"ADSIProg";
100 { 15,
"DISTINCTIVERING" },
102 { 17,
"REMINDERRING" },
103 { 18,
"SPECIALRING" },
119#define STATE_NORMAL 0
124#define MAX_RET_CODE 20
125#define MAX_SUB_LEN 255
126#define MAX_MAIN_LEN 1600
128#define ARG_STRING (1 << 0)
129#define ARG_NUMBER (1 << 1)
198 if ((strlen(src) > 1) && src[0] ==
'\"') {
204 if (maxlen > strlen(src) - 1)
205 maxlen = strlen(src) - 1;
206 memcpy(
out, src, maxlen);
207 ((
char *)
out)[maxlen] =
'\0';
212 if (sscanf(src,
"%30o", (
unsigned *)
out) != 1)
216 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
218 }
else if ((strlen(src) > 2) && (src[0] ==
'0') && (tolower(src[1]) ==
'x')) {
222 if (sscanf(src + 2,
"%30x", (
unsigned int *)
out) != 1)
226 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
232 if (sscanf(src,
"%30d", (
int *)
out) != 1)
236 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
245 char *
tmp = *
buf, *keyword;
249 while(*
tmp && (*
tmp < 33))
254 while(*
tmp && ((*
tmp > 32) || quoted)) {
266 while(*
tmp && (*
tmp < 33))
277 char dtmfstr[80], *
a;
281 ast_log(
LOG_WARNING,
"Expecting something to send for SENDDTMF at line %d of %s\n", lineno, script);
286 ast_log(
LOG_WARNING,
"Invalid token for SENDDTMF at line %d of %s\n", lineno, script);
298 ast_log(
LOG_WARNING,
"'%c' is not a valid DTMF tone at line %d of %s\n", *
a, lineno, script);
312 if (!page || !gline) {
313 ast_log(
LOG_WARNING,
"Expecting page and line number for GOTOLINE at line %d of %s\n", lineno, script);
317 if (!strcasecmp(page,
"INFO"))
319 else if (!strcasecmp(page,
"COMM"))
322 ast_log(
LOG_WARNING,
"Expecting either 'INFO' or 'COMM' page, got '%s' at line %d of %s\n", page, lineno, script);
327 ast_log(
LOG_WARNING,
"Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
345 if (!dir || !gline) {
346 ast_log(
LOG_WARNING,
"Expecting direction and number of lines for GOTOLINEREL at line %d of %s\n", lineno, script);
350 if (!strcasecmp(dir,
"UP"))
352 else if (!strcasecmp(dir,
"DOWN"))
355 ast_log(
LOG_WARNING,
"Expecting either 'UP' or 'DOWN' direction, got '%s' at line %d of %s\n", dir, lineno, script);
360 ast_log(
LOG_WARNING,
"Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
377 ast_log(
LOG_WARNING,
"Expecting number of milliseconds to wait at line %d of %s\n", lineno, script);
382 ast_log(
LOG_WARNING,
"Invalid delay milliseconds '%s' at line %d of %s\n", gtime, lineno, script);
407 ast_log(
LOG_WARNING,
"Invalid state number '%s' at line %d of %s\n", gstate, lineno, script);
422 ast_log(
LOG_WARNING,
"Clearing timer requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
439 for (x = 0; x <
state->numflags; x++) {
440 if (!strcasecmp(
state->flags[x].vname,
name))
441 return &
state->flags[x];
448 if (
state->numflags > 6) {
467 ast_log(
LOG_WARNING,
"Setting flag requires a flag number at line %d of %s\n", lineno, script);
477 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
482 buf[1] = ((
flag->id & 0x7) << 4) | 1;
494 ast_log(
LOG_WARNING,
"Clearing flag requires a flag number at line %d of %s\n", lineno, script);
504 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
509 buf[1] = ((
flag->id & 0x7) << 4);
525 ast_log(
LOG_WARNING,
"Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
564 for (x = 0; x <
state->numkeys; x++) {
565 if (!strcasecmp(
state->keys[x].vname,
name))
566 return &
state->keys[x];
569 if (
state->numkeys > 61) {
585 for (x = 0; x <
state->numsubs; x++) {
586 if (!strcasecmp(
state->subs[x].vname,
name))
587 return &
state->subs[x];
590 if (
state->numsubs > 127) {
606 for (x = 0; x <
state->numstates; x++) {
607 if (!strcasecmp(
state->states[x].vname,
name))
608 return &
state->states[x];
615 if (
state->numstates > 253) {
631 for (x = 0; x <
state->numdisplays; x++) {
632 if (!strcasecmp(
state->displays[x].vname,
name))
633 return &
state->displays[x];
640 if (
state->numdisplays > 61) {
647 state->numdisplays++;
649 return &
state->displays[
state->numdisplays-1];
654 char *tok, newkey[80];
655 int bytes, x, flagid = 0;
656 unsigned char keyid[6];
660 for (x = 0; x < 7; x++) {
664 if (!strcasecmp(tok,
"UNLESS")) {
667 ast_log(
LOG_WARNING,
"Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
669 ast_log(
LOG_WARNING,
"Invalid flag name '%s' at line %d of %s\n", tok, lineno, script);
671 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", newkey, lineno, script);
675 ast_log(
LOG_WARNING,
"Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
679 ast_log(
LOG_WARNING,
"Only 6 keys can be defined, ignoring '%s' at line %d of %s\n", tok, lineno, script);
692 buf[1] = (flagid & 0x7) << 3 | (x & 0x7);
693 for (bytes = 0; bytes < x; bytes++)
694 buf[bytes + 2] = keyid[bytes];
701 char *tok, dispname[80];
702 int line = 0,
flag = 0, cmd = 3;
707 ast_log(
LOG_WARNING,
"Invalid display name: %s at line %d of %s\n", tok ? tok :
"<nothing>", lineno, script);
712 ast_log(
LOG_WARNING,
"Display '%s' is undefined at line %d of %s\n", dispname, lineno, script);
716 if (!(tok =
get_token(&
args, script, lineno)) || strcasecmp(tok,
"AT")) {
723 ast_log(
LOG_WARNING,
"Invalid line: '%s' at line %d of %s\n", tok ? tok :
"<nothing>", lineno, script);
727 if ((tok =
get_token(&
args, script, lineno)) && !strcasecmp(tok,
"NOUPDATE")) {
732 if (tok && !strcasecmp(tok,
"UNLESS")) {
735 ast_log(
LOG_WARNING,
"Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
737 ast_log(
LOG_WARNING,
"Invalid flag number '%s' at line %d of %s\n", tok, lineno, script);
740 ast_log(
LOG_WARNING,
"Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
744 buf[1] = (cmd << 6) | (disp->
id & 0x3f);
745 buf[2] = ((line & 0x1f) << 3) | (
flag & 0x7);
755 ast_log(
LOG_WARNING,
"Clearing display requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
767 ast_log(
LOG_WARNING,
"Digitdirect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
779 ast_log(
LOG_WARNING,
"CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
791 ast_log(
LOG_WARNING,
"Digitcollect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
810 ast_log(
LOG_WARNING,
"Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
826 char subscr[80], sname[80];
827 int sawin = 0,
event, snums[8], scnt = 0, x;
831 ast_log(
LOG_WARNING,
"Missing event for 'ONEVENT' at line %d of %s\n", lineno, script);
841 while ((!sawin && !strcasecmp(tok,
"IN")) || (sawin && !strcasecmp(tok,
"OR"))) {
844 ast_log(
LOG_WARNING,
"No more than 8 states may be specified for inclusion at line %d of %s\n", lineno, script);
850 ast_log(
LOG_WARNING,
"'%s' is not a valid state name at line %d of %s\n", tok, lineno, script);
854 ast_log(
LOG_WARNING,
"State '%s' not declared at line %d of %s\n", sname, lineno, script);
861 if (!tok || strcasecmp(tok,
"GOTO")) {
865 ast_log(
LOG_WARNING,
"Got '%s' while looking for 'GOTO' or 'OR' at line %d of %s\n", tok, lineno, script);
867 ast_log(
LOG_WARNING,
"Got '%s' while looking for 'GOTO' or 'IN' at line %d of %s\n", tok, lineno, script);
874 ast_log(
LOG_WARNING,
"Invalid subscript '%s' at line %d of %s\n", tok, lineno, script);
882 for (x = 0; x < scnt; x++)
883 buf[3 + x] = snums[x];
899 {
"WAITDIALTONE", 0x84 },
902 {
"SENDCHARS", 0x87 },
903 {
"CLEARCHARS", 0x88 },
904 {
"BACKSPACE", 0x89 },
909 {
"PAGEDOWN", 0x8e },
912 {
"DIALPULSEONE", 0x91 },
913 {
"DATAMODE", 0x92 },
914 {
"VOICEMODE", 0x93 },
994 if ((
sub->datalen + res + 1) <=
max)
1003 if ((
sub->datalen + 2) <=
max) {
1012 sub->data[
sub->datalen] = 0xff;
1024 char *
args, vname[256],
tmp[80], tmp2[80];
1025 int lrci, wi,
event;
1032 switch(
state->state) {
1034 if (!strcasecmp(keyword,
"DESCRIPTION")) {
1037 ast_log(
LOG_WARNING,
"'%s' is not a valid token for DESCRIPTION at line %d of %s\n",
args, lineno, script);
1039 ast_log(
LOG_WARNING,
"Missing argument for DESCRIPTION at line %d of %s\n", lineno, script);
1040 }
else if (!strcasecmp(keyword,
"VERSION")) {
1045 ast_log(
LOG_WARNING,
"Missing argument for VERSION at line %d of %s\n", lineno, script);
1046 }
else if (!strcasecmp(keyword,
"SECURITY")) {
1051 ast_log(
LOG_WARNING,
"Missing argument for SECURITY at line %d of %s\n", lineno, script);
1052 }
else if (!strcasecmp(keyword,
"FDN")) {
1058 }
else if (!strcasecmp(keyword,
"KEY")) {
1060 ast_log(
LOG_WARNING,
"KEY definition missing name at line %d of %s\n", lineno, script);
1064 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1071 if (
state->key->defined) {
1080 ast_log(
LOG_WARNING,
"KEY definition missing short name at line %d of %s\n", lineno, script);
1084 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY short name at line %d of %s\n",
args, lineno, script);
1088 if (strcasecmp(
args,
"OR")) {
1093 ast_log(
LOG_WARNING,
"KEY definition missing optional long name at line %d of %s\n", lineno, script);
1097 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY long name at line %d of %s\n",
args, lineno, script);
1103 if (strlen(tmp2) > 18) {
1104 ast_log(
LOG_WARNING,
"Truncating full name to 18 characters at line %d of %s\n", lineno, script);
1107 if (strlen(
tmp) > 7) {
1108 ast_log(
LOG_WARNING,
"Truncating short name to 7 bytes at line %d of %s\n", lineno, script);
1112 state->key->retstr[0] = 0x80;
1116 memcpy(
state->key->retstr + 3, tmp2, strlen(tmp2));
1118 state->key->retstrlen = strlen(tmp2) + 3;
1120 state->key->retstr[
state->key->retstrlen++] = 0xff;
1124 state->key->retstrlen += strlen(
tmp);
1126 state->key->retstr[
state->key->retstrlen++] = 0xff;
1130 }
else if (!strcasecmp(keyword,
"SUB")) {
1132 ast_log(
LOG_WARNING,
"SUB definition missing name at line %d of %s\n", lineno, script);
1136 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1143 if (
state->sub->defined) {
1148 state->sub->data[0] = 0x82;
1150 state->sub->data[2] = 0x0;
1151 state->sub->datalen = 3;
1152 if (
state->sub->id) {
1154 state->sub->data[3] = 9;
1157 state->sub->data[6] = 0xff;
1158 state->sub->datalen = 7;
1165 }
else if (!strcasecmp(keyword,
"STATE")) {
1167 ast_log(
LOG_WARNING,
"STATE definition missing name at line %d of %s\n", lineno, script);
1171 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a STATE name at line %d of %s\n",
args, lineno, script);
1179 }
else if (!strcasecmp(keyword,
"FLAG")) {
1181 ast_log(
LOG_WARNING,
"FLAG definition missing name at line %d of %s\n", lineno, script);
1185 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a FLAG name at line %d of %s\n",
args, lineno, script);
1193 }
else if (!strcasecmp(keyword,
"DISPLAY")) {
1197 ast_log(
LOG_WARNING,
"SUB definition missing name at line %d of %s\n", lineno, script);
1201 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1222 if (strlen(
tmp) > 20) {
1223 ast_log(
LOG_WARNING,
"Truncating column one to 20 characters at line %d of %s\n", lineno, script);
1233 if (strlen(
tmp) > 20) {
1234 ast_log(
LOG_WARNING,
"Truncating column two to 20 characters at line %d of %s\n", lineno, script);
1242 if (!strcasecmp(
args,
"JUSTIFY")) {
1245 ast_log(
LOG_WARNING,
"Qualifier 'JUSTIFY' requires an argument at line %d of %s\n", lineno, script);
1253 }
else if (!strcasecmp(
args,
"WRAP")) {
1265 disp->
data[0] = 0x81;
1267 disp->
data[2] = ((lrci & 0x3) << 6) | disp->
id;
1269 disp->
data[4] = 0xff;
1276 if (!strcasecmp(keyword,
"ENDKEY")) {
1279 state->key->defined = 1;
1280 state->key->retstr[1] =
state->key->retstrlen - 2;
1283 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in SOFTKEY definition at line %d of %s\n", keyword, lineno, script);
1289 if (!strcasecmp(keyword,
"ENDIF")) {
1292 state->sub->defined = 1;
1294 state->sub->ifdata[2] =
state->sub->ifinscount;
1295 }
else if (!strcasecmp(keyword,
"GOTO")) {
1297 ast_log(
LOG_WARNING,
"GOTO clause missing Subscript name at line %d of %s\n", lineno, script);
1301 ast_log(
LOG_WARNING,
"'%s' is not a valid subscript name token at line %d of %s\n",
args, lineno, script);
1307 state->sub->data[
state->sub->datalen++] = 0x8;
1311 state->sub->data[
state->sub->datalen++] = 0xff;
1313 state->sub->inscount++;
1314 state->sub->ifinscount++;
1316 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in IF clause at line %d of %s\n", keyword, lineno, script);
1319 state->sub->ifinscount++;
1323 if (!strcasecmp(keyword,
"ENDSUB")) {
1326 state->sub->defined = 1;
1328 state->sub->data[1] =
state->sub->datalen - 2;
1329 if (
state->sub->id) {
1334 }
else if (!strcasecmp(keyword,
"IFEVENT")) {
1336 ast_log(
LOG_WARNING,
"IFEVENT clause missing Event name at line %d of %s\n", lineno, script);
1344 ast_log(
LOG_WARNING,
"IFEVENT clause missing 'THEN' at line %d of %s\n", lineno, script);
1347 state->sub->ifinscount = 0;
1350 state->sub->ifdata[0] = 0x1;
1353 state->sub->ifdata[3] = 0xff;
1354 state->sub->datalen += 4;
1356 state->sub->inscount++;
1359 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in SUB definition at line %d of %s\n", keyword, lineno, script);
1372 char fn[256],
buf[256], *
c;
1373 int lineno = 0, x, err;
1376 if (script[0] ==
'/')
1381 if (!(f = fopen(fn,
"r"))) {
1394 if (!fgets(
buf,
sizeof(
buf), f)) {
1400 buf[strlen(
buf) - 1] =
'\0';
1402 if ((
c = strchr(
buf,
';')))
1410 switch(scr->
state) {
1425 for (x = 0; x < scr->
numkeys; x++) {
1433 for (x = 0; x < scr->
numsubs; x++) {
1438 if (x == (scr->
numsubs - 1)) {
1452static void dump_message(
char *
type,
char *vname,
unsigned char *
buf,
int buflen)
1455 printf(
"%s %s: [ ",
type, vname);
1456 for (x = 0; x < buflen; x++)
1457 printf(
"%02hhx ",
buf[x]);
1466 unsigned char buf[1024];
1478 ast_verb(3,
"User rejected download attempt\n");
1486 for (x = 0; x < scr->
numkeys; x++) {
1534 for (x = 0; x < scr->
numsubs; x++) {
1563 ast_verb(3,
"Download attempt failed\n");
1578 data =
"asterisk.adsi";
1581 ast_verb(3,
"ADSI Unavailable on CPE. Not bothering to try.\n");
1583 ast_verb(3,
"ADSI Available on CPE. Attempting Upload.\n");
1616 .
requires =
"res_adsi",
ADSI Support (built upon Caller*ID)
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
#define ADSI_MSG_DOWNLOAD
int ast_adsi_unload_session(struct ast_channel *chan)
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay,...
int ast_adsi_end_download(struct ast_channel *chan)
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
static int process_returncode(struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
static int cleardisplay(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int process_token(void *out, char *src, int maxlen, int argtype)
static int clearflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static const struct adsi_event events[]
static int goto_line(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_script * compile_script(const char *script)
static int showkeys(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_flag * getflagbyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int adsi_exec(struct ast_channel *chan, const char *data)
static struct adsi_soft_key * getkeybyname(struct adsi_script *state, char *name, const char *script, int lineno)
static int subscript(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_subscript * getsubbyname(struct adsi_script *state, char *name, const char *script, int lineno)
static int geteventbyname(char *name)
static int process_opcode(struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
static int adsi_process(struct adsi_script *state, char *buf, const char *script, int lineno)
static int send_delay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int cleartimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static const struct adsi_key_cmd kcmds[]
static int adsi_prog(struct ast_channel *chan, const char *script)
static int goto_line_rel(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_display * getdisplaybyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int setflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int set_state(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int starttimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static const struct adsi_key_cmd opcmds[]
static int load_module(void)
Load the module.
static int getjustifybyname(char *name)
static int onevent(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int unload_module(void)
static char * get_token(char **buf, const char *script, int lineno)
static struct adsi_state * getstatebyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int send_dtmf(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static const struct adsi_event justify[]
static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_calloc(num, len)
A wrapper for calloc()
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
Generic File Format Support. Should be included by clients of the file handling routines....
#define ast_verb(level,...)
Asterisk locking-related definitions:
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_DEPRECATED
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_CONFIG_DIR
Core PBX routines and definitions.
struct stasis_forward * sub
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int(* add_args)(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
struct adsi_subscript subs[128]
struct adsi_subscript * sub
struct adsi_state states[256]
struct adsi_flag flags[7]
struct adsi_display displays[63]
struct adsi_soft_key keys[62]
struct adsi_soft_key * key
Main Channel structure associated with a channel.