static int _ast_adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice) { unsigned char buf[256] = ""; int bytes = 0, res; bytes += ast_adsi_data_mode(buf); ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0); bytes = 0; bytes += ast_adsi_query_cpeinfo(buf); ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0); /* Get width */ if ((res = ast_readstring(chan, (char *)buf, 2, 1000, 500, "")) < 0) return res; if (strlen((char *)buf) != 2) { ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res); res = 0; } else { res = 1; } if (width) *width = atoi((char *)buf); /* Get height */ memset(buf, 0, sizeof(buf)); if (res) { if ((res = ast_readstring(chan, (char *)buf, 2, 1000, 500, "")) < 0) return res; if (strlen((char *)buf) != 2) { ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res); res = 0; } else { res = 1; } if (height) *height= atoi((char *)buf); } /* Get buttons */ memset(buf, 0, sizeof(buf)); if (res) { if ((res = ast_readstring(chan, (char *)buf, 1, 1000, 500, "")) < 0) return res; if (strlen((char *)buf) != 1) { ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res); res = 0; } else { res = 1; } if (buttons) *buttons = atoi((char *)buf); } if (voice) { bytes = 0; bytes += ast_adsi_voice_mode(buf, 0); ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0); /* Ignore the resulting DTMF B announcing it's in voice mode */ ast_waitfordigit(chan, 1000); } return res; }
static int _ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data) { unsigned char dsp[256] = ""; int bytes = 0, res; char resp[2]; /* Connect to session */ bytes += ast_adsi_connect_session(dsp + bytes, app, ver); if (data) bytes += ast_adsi_data_mode(dsp + bytes); /* Prepare key setup messages */ if (ast_adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0)) return -1; if (app) { if ((res = ast_readstring(chan, resp, 1, 1200, 1200, "")) < 0) return -1; if (res) { ast_debug(1, "No response from CPE about version. Assuming not there.\n"); return 0; } if (!strcmp(resp, "B")) { ast_debug(1, "CPE has script '%s' version %d already loaded\n", app, ver); return 1; } else if (!strcmp(resp, "A")) { ast_debug(1, "CPE hasn't script '%s' version %d already loaded\n", app, ver); } else { ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp); } } else return 1; return 0; }
int adsi_begin_download(struct ast_channel *chan, char *service, char *fdn, char *sec, int version) { int bytes; unsigned char buf[256]; char ack[2]; bytes = 0; /* Setup the resident soft key stuff, a piece at a time */ /* Upload what scripts we can for voicemail ahead of time */ bytes += adsi_download_connect(buf + bytes, service, fdn, sec, version); if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) return -1; if (ast_readstring(chan, ack, 1, 10000, 10000, "")) return -1; if (ack[0] == 'B') return 0; ast_log(LOG_DEBUG, "Download was denied by CPE\n"); return -1; }
/* set timeout to 0 for "standard" timeouts. Set timeout to -1 for "ludicrous time" (essentially never times out) */ int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout) { int res,to,fto; /* XXX Merge with full version? XXX */ if (maxlen) s[0] = '\0'; if (prompt) { res = ast_streamfile(c, prompt, c->language); if (res < 0) return res; } fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000; to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; if (timeout > 0) fto = to = timeout; if (timeout < 0) fto = to = 1000000000; res = ast_readstring(c, s, maxlen, to, fto, "#"); return res; }
int AST_OPTIONAL_API_NAME(ast_adsi_begin_download)(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version) { int bytes = 0; unsigned char buf[256]; char ack[2]; /* Setup the resident soft key stuff, a piece at a time */ /* Upload what scripts we can for voicemail ahead of time */ bytes += ast_adsi_download_connect(buf + bytes, service, fdn, sec, version); if (ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0)) { return -1; } if (ast_readstring(chan, ack, 1, 10000, 10000, "")) { return -1; } if (ack[0] == 'B') { return 0; } ast_debug(1, "Download was denied by CPE\n"); return -1; }
static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype) { /* msglen must be no more than 256 bits, each */ unsigned char buf[24000 * 5]; int pos = 0, res; int x; int start=0; int retries = 0; char ack[3]; /* Wait up to 500 ms for initial ACK */ int waittime; struct ast_frame *f; int rem = 0; int def; if (chan->adsicpe == AST_ADSI_UNAVAILABLE) { /* Don't bother if we know they don't support ADSI */ errno = ENOSYS; return -1; } while(retries < maxretries) { if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) { /* Generate CAS (no SAS) */ ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW); /* Send CAS */ if (adsi_careful_send(chan, buf, 680, NULL)) { ast_log(LOG_WARNING, "Unable to send CAS\n"); } /* Wait For DTMF result */ waittime = 500; for(;;) { if (((res = ast_waitfor(chan, waittime)) < 1)) { /* Didn't get back DTMF A in time */ ast_log(LOG_DEBUG, "No ADSI CPE detected (%d)\n", res); if (!chan->adsicpe) chan->adsicpe = AST_ADSI_UNAVAILABLE; errno = ENOSYS; return -1; } waittime = res; f = ast_read(chan); if (!f) { ast_log(LOG_DEBUG, "Hangup in ADSI\n"); return -1; } if (f->frametype == AST_FRAME_DTMF) { if (f->subclass == 'A') { /* Okay, this is an ADSI CPE. Note this for future reference, too */ if (!chan->adsicpe) chan->adsicpe = AST_ADSI_AVAILABLE; break; } else { if (f->subclass == 'D') { ast_log(LOG_DEBUG, "Off-hook capable CPE only, not ADSI\n"); } else ast_log(LOG_WARNING, "Unknown ADSI response '%c'\n", f->subclass); if (!chan->adsicpe) chan->adsicpe = AST_ADSI_UNAVAILABLE; errno = ENOSYS; return -1; } } ast_frfree(f); } ast_log(LOG_DEBUG, "ADSI Compatible CPE Detected\n"); } else ast_log(LOG_DEBUG, "Already in data mode\n"); x = 0; pos = 0; #if 1 def= ast_channel_defer_dtmf(chan); #endif while((x < 6) && msg[x]) { res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW); if (res < 0) { ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name); return -1; } ast_log(LOG_DEBUG, "Message %d, of %d input bytes, %d output bytes\n", x + 1, msglen[x], res); pos += res; x++; } rem = 0; res = adsi_careful_send(chan, buf, pos, &rem); if (!def) ast_channel_undefer_dtmf(chan); if (res) return -1; ast_log(LOG_DEBUG, "Sent total spill of %d bytes\n", pos); memset(ack, 0, sizeof(ack)); /* Get real result */ res = ast_readstring(chan, ack, 2, 1000, 1000, ""); /* Check for hangup */ if (res < 0) return -1; if (ack[0] == 'D') { ast_log(LOG_DEBUG, "Acked up to message %d\n", atoi(ack + 1)); start += atoi(ack + 1); if (start >= x) break; else { retries++; ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", retries, start + 1); } } else { retries++; ast_log(LOG_WARNING, "Unexpected response to ack: %s (retry %d)\n", ack, retries); } } if (retries >= maxretries) { ast_log(LOG_WARNING, "Maximum ADSI Retries (%d) exceeded\n", maxretries); errno = ETIMEDOUT; return -1; } return 0; }
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int last, int readext, int fromappvm) { /* Read in the first three digits.. "digit" is the first digit, already read */ char ext[NUMDIGITS + 1], *cat; char name[80] = ""; struct ast_variable *v; int res; int found=0; int lastuserchoice = 0; char *start, *conv, *stringp = NULL; const char *pos; int breakout = 0; if (ast_strlen_zero(context)) { ast_log(LOG_WARNING, "Directory must be called with an argument " "(context in which to interpret extensions)\n"); return -1; } if (digit == '0') { if (!ast_goto_if_exists(chan, dialcontext, "o", 1) || (!ast_strlen_zero(chan->macrocontext) && !ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) { return 0; } else { ast_log(LOG_WARNING, "Can't find extension 'o' in current context. " "Not Exiting the Directory!\n"); res = 0; } } if (digit == '*') { if (!ast_goto_if_exists(chan, dialcontext, "a", 1) || (!ast_strlen_zero(chan->macrocontext) && !ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) { return 0; } else { ast_log(LOG_WARNING, "Can't find extension 'a' in current context. " "Not Exiting the Directory!\n"); res = 0; } } memset(ext, 0, sizeof(ext)); ext[0] = digit; res = 0; if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1; if (!res) { /* Search for all names which start with those digits */ v = ast_variable_browse(cfg, context); while(v && !res) { /* Find all candidate extensions */ while(v) { /* Find a candidate extension */ start = strdup(v->value); if (start && !strcasestr(start, "hidefromdir=yes")) { stringp=start; strsep(&stringp, ","); pos = strsep(&stringp, ","); if (pos) { ast_copy_string(name, pos, sizeof(name)); /* Grab the last name */ if (last && strrchr(pos,' ')) pos = strrchr(pos, ' ') + 1; conv = convert(pos); if (conv) { if (!strncmp(conv, ext, strlen(ext))) { /* Match! */ found++; free(conv); free(start); break; } free(conv); } } free(start); } v = v->next; } if (v) { /* We have a match -- play a greeting if they have it */ res = play_mailbox_owner(chan, context, dialcontext, v->name, name, readext, fromappvm); switch (res) { case -1: /* user pressed '1' but extension does not exist, or * user hungup */ lastuserchoice = 0; break; case '1': /* user pressed '1' and extensions exists; play_mailbox_owner will already have done a goto() on the channel */ lastuserchoice = res; break; case '*': /* user pressed '*' to skip something found */ lastuserchoice = res; res = 0; break; default: break; } v = v->next; } } if (!res && ucfg) { /* Search users.conf for all names which start with those digits */ for (cat = ast_category_browse(ucfg, NULL); cat && !res ; cat = ast_category_browse(ucfg, cat)) { if (!strcasecmp(cat, "general")) continue; if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) continue; /* Find all candidate extensions */ if ((pos = ast_variable_retrieve(ucfg, cat, "fullname"))) { ast_copy_string(name, pos, sizeof(name)); /* Grab the last name */ if (last && strrchr(pos,' ')) pos = strrchr(pos, ' ') + 1; conv = convert(pos); if (conv) { if (!strcmp(conv, ext)) { /* Match! */ found++; /* We have a match -- play a greeting if they have it */ res = play_mailbox_owner(chan, context, dialcontext, cat, name, readext, fromappvm); switch (res) { case -1: /* user pressed '1' but extension does not exist, or * user hungup */ lastuserchoice = 0; breakout = 1; break; case '1': /* user pressed '1' and extensions exists; play_mailbox_owner will already have done a goto() on the channel */ lastuserchoice = res; breakout = 1; break; case '*': /* user pressed '*' to skip something found */ lastuserchoice = res; breakout = 0; res = 0; break; default: breakout = 1; break; } free(conv); if (breakout) break; } else free(conv); } } } } if (lastuserchoice != '1') { res = ast_streamfile(chan, found ? "dir-nomore" : "dir-nomatch", chan->language); if (!res) res = 1; return res; } return 0; } return res; }