Interface header for PRI signaling module. More...
#include "asterisk/channel.h"#include "asterisk/frame.h"#include "asterisk/event.h"#include "asterisk/ccss.h"#include <libpri.h>#include <dahdi/user.h>

Go to the source code of this file.
Interface header for PRI signaling module.
Definition in file sig_pri.h.
| #define DAHDI_CHAN_MAPPING_LOGICAL 1 |
Definition at line 167 of file sig_pri.h.
Referenced by process_dahdi(), and sig_pri_start_pri().
| #define DAHDI_CHAN_MAPPING_PHYSICAL 0 |
Definition at line 166 of file sig_pri.h.
Referenced by dahdi_chan_conf_default(), and process_dahdi().
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 173 of file sig_pri.h.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 172 of file sig_pri.h.
Referenced by dahdi_handle_event(), dahdi_read(), process_dahdi(), pri_ss_thread(), pri_dchannel(), and sig_pri_cli_show_span().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 170 of file sig_pri.h.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 171 of file sig_pri.h.
Referenced by dahdi_read(), process_dahdi(), pri_dchannel(), and sig_pri_start_pri().
| #define SIG_PRI_AOC_GRANT_D (1 << 1) |
Definition at line 67 of file sig_pri.h.
Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().
| #define SIG_PRI_AOC_GRANT_E (1 << 2) |
Definition at line 68 of file sig_pri.h.
Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().
| #define SIG_PRI_AOC_GRANT_S (1 << 0) |
Definition at line 66 of file sig_pri.h.
Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().
| #define SIG_PRI_DEBUG_DEFAULT 0 |
PRI debug message flags set on initial startup.
Definition at line 63 of file sig_pri.h.
Referenced by sig_pri_start_pri().
| #define SIG_PRI_DEBUG_INTENSE |
(PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE \ | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP)
PRI debug message flags when intense PRI debugging is turned on at the command line.
Definition at line 53 of file sig_pri.h.
Referenced by handle_pri_debug().
| #define SIG_PRI_DEBUG_NORMAL (PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE) |
PRI debug message flags when normal PRI debugging is turned on at the command line.
Definition at line 49 of file sig_pri.h.
Referenced by handle_pri_debug().
| #define SIG_PRI_MAX_CHANNELS 672 |
| #define SIG_PRI_NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 158 of file sig_pri.h.
Referenced by pri_create_trunkgroup(), mkintf(), dahdi_pri_message(), dahdi_pri_error(), prepare_pri(), handle_pri_debug(), handle_pri_show_debug(), dahdi_restart(), __unload_module(), setup_dahdi_int(), pri_is_up(), pri_active_dchan_index(), pri_find_dchan(), pri_dchannel(), sig_pri_init_pri(), sig_pri_start_pri(), sig_pri_cli_show_spans(), and sig_pri_cli_show_span().
| enum sig_pri_call_level |
Call establishment life cycle level for simple comparisons.
Definition at line 87 of file sig_pri.h.
{
/*! Call does not exist. */
SIG_PRI_CALL_LEVEL_IDLE,
/*! Call is present but has no response yet. (SETUP) */
SIG_PRI_CALL_LEVEL_SETUP,
/*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
SIG_PRI_CALL_LEVEL_OVERLAP,
/*! Call routing is happening. (PROCEEDING) */
SIG_PRI_CALL_LEVEL_PROCEEDING,
/*! Called party is being alerted of the call. (ALERTING) */
SIG_PRI_CALL_LEVEL_ALERTING,
/*! Call is connected/answered. (CONNECT) */
SIG_PRI_CALL_LEVEL_CONNECT,
};
| enum sig_pri_law |
Definition at line 80 of file sig_pri.h.
{
SIG_PRI_DEFLAW = 0,
SIG_PRI_ULAW,
SIG_PRI_ALAW
};
| enum sig_pri_tone |
| void pri_event_alarm | ( | struct sig_pri_span * | pri, |
| int | index, | ||
| int | before_start_pri | ||
| ) |
Definition at line 1897 of file sig_pri.c.
References sig_pri_span::dchanavail, DCHAN_NOTINALARM, DCHAN_UP, and pri_find_dchan().
Referenced by my_handle_dchan_exception(), and prepare_pri().
{
pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
if (!before_start_pri)
pri_find_dchan(pri);
}
| void pri_event_noalarm | ( | struct sig_pri_span * | pri, |
| int | index, | ||
| int | before_start_pri | ||
| ) |
Definition at line 1904 of file sig_pri.c.
References sig_pri_span::dchanavail, DCHAN_NOTINALARM, and sig_pri_span::dchans.
Referenced by my_handle_dchan_exception(), and prepare_pri().
{
pri->dchanavail[index] |= DCHAN_NOTINALARM;
if (!before_start_pri)
pri_restart(pri->dchans[index]);
}
| int pri_is_up | ( | struct sig_pri_span * | pri | ) |
Definition at line 995 of file sig_pri.c.
References SIG_PRI_NUM_DCHANS, sig_pri_span::dchanavail, and DCHAN_AVAILABLE.
Referenced by pri_dchannel().
{
int x;
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchanavail[x] == DCHAN_AVAILABLE)
return 1;
}
return 0;
}
| int pri_send_callrerouting_facility_exec | ( | struct sig_pri_chan * | p, |
| enum ast_channel_state | chanstate, | ||
| const char * | destination, | ||
| const char * | original, | ||
| const char * | reason | ||
| ) |
Definition at line 7804 of file sig_pri.c.
References sig_pri_lock_private(), sig_pri_chan::pri, sig_pri_chan::call, ast_log(), LOG_DEBUG, sig_pri_unlock_private(), pri_grab(), sig_pri_span::pri, pri_rel(), and sig_pri_span::span.
{
int res = -1;
sig_pri_lock_private(p);
if (!p->pri || !p->call) {
ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
sig_pri_unlock_private(p);
return -1;
}
if (!pri_grab(p, p->pri)) {
res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
pri_rel(p->pri);
} else {
ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->pri->span);
}
sig_pri_unlock_private(p);
return res;
}
| int pri_send_keypad_facility_exec | ( | struct sig_pri_chan * | p, |
| const char * | digits | ||
| ) |
Definition at line 7780 of file sig_pri.c.
References sig_pri_lock_private(), sig_pri_chan::pri, sig_pri_chan::call, ast_debug, sig_pri_unlock_private(), pri_grab(), sig_pri_span::pri, and pri_rel().
Referenced by dahdi_send_keypad_facility_exec().
{
sig_pri_lock_private(p);
if (!p->pri || !p->call) {
ast_debug(1, "Unable to find pri or call on channel!\n");
sig_pri_unlock_private(p);
return -1;
}
if (!pri_grab(p, p->pri)) {
pri_keypad_facility(p->pri->pri, p->call, digits);
pri_rel(p->pri);
} else {
ast_debug(1, "Unable to grab pri to send keypad facility!\n");
sig_pri_unlock_private(p);
return -1;
}
sig_pri_unlock_private(p);
return 0;
}
| int sig_pri_answer | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast | ||
| ) |
Definition at line 7070 of file sig_pri.c.
References pri_grab(), sig_pri_chan::pri, sig_pri_span::pri, sig_pri_chan::call, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_CONNECT, sig_pri_set_dialing(), sig_pri_open_media(), sig_pri_chan::digital, pri_rel(), ast_setstate(), and AST_STATE_UP.
Referenced by dahdi_answer().
{
int res = 0;
/* Send a pri acknowledge */
if (!pri_grab(p, p->pri)) {
#if defined(HAVE_PRI_AOC_EVENTS)
if (p->aoc_s_request_invoke_id_valid) {
/* if AOC-S was requested and the invoke id is still present on answer. That means
* no AOC-S rate list was provided, so send a NULL response which will indicate that
* AOC-S is not available */
pri_aoc_s_request_response_send(p->pri->pri, p->call,
p->aoc_s_request_invoke_id, NULL);
p->aoc_s_request_invoke_id_valid = 0;
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
p->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
}
sig_pri_set_dialing(p, 0);
sig_pri_open_media(p);
res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
pri_rel(p->pri);
} else {
res = -1;
}
ast_setstate(ast, AST_STATE_UP);
return res;
}
| int sig_pri_available | ( | struct sig_pri_chan ** | pvt, |
| int | is_specific_channel | ||
| ) |
Definition at line 7167 of file sig_pri.c.
References sig_pri_span::pri, sig_pri_chan::pri, ast_mutex_lock, sig_pri_span::lock, sig_pri_available_check(), sig_pri_chan::allocated, and ast_mutex_unlock.
Referenced by available().
{
struct sig_pri_chan *p = *pvt;
struct sig_pri_span *pri;
if (!p->pri) {
/* Something is wrong here. A PRI channel without the pri pointer? */
return 0;
}
pri = p->pri;
ast_mutex_lock(&pri->lock);
if (
#if defined(HAVE_PRI_CALL_WAITING)
/*
* Only do call waiting calls if we have any
* call waiting call outstanding. We do not
* want new calls to steal a B channel
* freed for an earlier call waiting call.
*/
!pri->num_call_waiting_calls &&
#endif /* defined(HAVE_PRI_CALL_WAITING) */
sig_pri_available_check(p)) {
p->allocated = 1;
ast_mutex_unlock(&pri->lock);
return 1;
}
#if defined(HAVE_PRI_CALL_WAITING)
if (!is_specific_channel) {
struct sig_pri_chan *cw;
cw = sig_pri_cw_available(pri);
if (cw) {
/* We have a call waiting interface to use instead. */
cw->allocated = 1;
*pvt = cw;
ast_mutex_unlock(&pri->lock);
return 1;
}
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
ast_mutex_unlock(&pri->lock);
return 0;
}
| int sig_pri_call | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast, | ||
| char * | rdest, | ||
| int | timeout, | ||
| int | layer1 | ||
| ) |
Definition at line 6400 of file sig_pri.c.
References AST_DECLARE_APP_ARGS, args, AST_APP_ARG, ext, OPT_ARG_ARRAY_SIZE, ast_log(), LOG_DEBUG, S_COR, ast_channel::connected, ast_party_connected_line::id, ast_party_id::name, ast_party_name::valid, ast_party_name::str, ast_party_id::number, ast_party_number::valid, ast_party_number::str, sig_pri_chan::pri, LOG_ERROR, sig_pri_chan::channel, ast_channel::_state, AST_STATE_DOWN, AST_STATE_RESERVED, LOG_WARNING, ast_channel::name, sig_pri_chan::dialdest, sig_pri_chan::outgoing, ast_copy_string(), AST_NONSTANDARD_APP_ARGS, ast_app_parse_options(), sig_pri_call_opts, ast_party_subaddress_init(), ast_party_subaddress::type, ast_party_subaddress::str, ast_party_subaddress::valid, sig_pri_chan::hidecallerid, sig_pri_chan::hidecalleridname, sig_pri_chan::stripmsd, pri_grab(), sig_pri_chan::call, sig_pri_span::pri, pri_rel(), sig_pri_set_digital(), IS_DIGITAL, ast_channel::transfercapability, sig_pri_chan::priexclusive, sig_pri_span::nodetype, PVT_TO_CHANNEL(), sig_pri_chan::digital, PRI_TRANS_CAP_DIGITAL, sig_pri_span::facilityenable, ast_verb, ast_transfercapability2str(), sig_pri_span::dialplan, sig_pri_span::internationalprefix, sig_pri_span::nationalprefix, ast_test_flag, OPT_KEYPAD, ast_strlen_zero(), OPT_ARG_KEYPAD, OPT_REVERSE_CHARGE, OPT_AOC_REQUEST, OPT_ARG_AOC_REQUEST, sig_pri_span::append_msn_to_user_tag, sig_pri_chan::user_tag, sig_pri_span::initial_user_tag, ast_free, ast_channel::caller, ast_party_caller::id, ast_party_id::tag, ast_strdup, sig_pri_span::localdialplan, sig_pri_chan::use_callingpres, ast_party_number::presentation, ast_party_id::subaddress, sig_pri_redirecting_update(), pbx_builtin_getvar_helper(), sig_pri_chan::owner, ast_cc_is_recall(), monitor, AST_CHANNEL_NAME, ast_channel_get_device_name(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor::private_data, ast_assert, ao2_ref, dialplan2str(), sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_SETUP, ast_setstate(), AST_STATE_DIALING, and sig_pri_set_dialing().
Referenced by dahdi_call().
{
char dest[256]; /* must be same length as p->dialdest */
struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
struct pri_sr *sr;
char *c, *l, *n, *s;
#ifdef SUPPORT_USERUSER
const char *useruser;
#endif
int core_id;
int pridialplan;
int dp_strip;
int prilocaldialplan;
int ldp_strip;
int exclusive;
#if defined(HAVE_PRI_SETUP_KEYPAD)
const char *keypad;
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(group); /* channel/group token */
AST_APP_ARG(ext); /* extension token */
AST_APP_ARG(opts); /* options token */
AST_APP_ARG(other); /* Any remining unused arguments */
);
struct ast_flags opts;
char *opt_args[OPT_ARG_ARRAY_SIZE];
ast_log(LOG_DEBUG, "CALLER NAME: %s NUM: %s\n",
S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
if (!p->pri) {
ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
return -1;
}
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
return -1;
}
p->dialdest[0] = '\0';
p->outgoing = 1;
ast_copy_string(dest, rdest, sizeof(dest));
AST_NONSTANDARD_APP_ARGS(args, dest, '/');
if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
/* General invalid option syntax. */
return -1;
}
c = args.ext;
if (!c) {
c = "";
}
/* setup dialed_subaddress if found */
ast_party_subaddress_init(&dialed_subaddress);
s = strchr(c, ':');
if (s) {
*s = '\0';
s++;
/* prefix */
/* 'n' = NSAP */
/* 'u' = User Specified */
/* Default = NSAP */
switch (*s) {
case 'U':
case 'u':
s++;
dialed_subaddress.type = 2;
break;
case 'N':
case 'n':
s++;
/* default already covered with ast_party_subaddress_init */
break;
}
dialed_subaddress.str = s;
dialed_subaddress.valid = 1;
s = NULL;
}
l = NULL;
n = NULL;
if (!p->hidecallerid) {
if (ast->connected.id.number.valid) {
/* If we get to the end of this loop without breaking, there's no
* calleridnum. This is done instead of testing for "unknown" or
* the thousands of other ways that the calleridnum could be
* invalid. */
for (l = ast->connected.id.number.str; l && *l; l++) {
if (strchr("0123456789", *l)) {
l = ast->connected.id.number.str;
break;
}
}
} else {
l = NULL;
}
if (!p->hidecalleridname) {
n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
}
}
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
return -1;
}
if (pri_grab(p, p->pri)) {
ast_log(LOG_WARNING, "Failed to grab PRI!\n");
return -1;
}
if (!(p->call = pri_new_call(p->pri->pri))) {
ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
pri_rel(p->pri);
return -1;
}
if (!(sr = pri_sr_new())) {
ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
return -1;
}
sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability)); /* push up to parent for EC */
#if defined(HAVE_PRI_CALL_WAITING)
if (p->is_call_waiting) {
/*
* Indicate that this is a call waiting call.
* i.e., Normal call but with no B channel.
*/
pri_sr_set_channel(sr, 0, 0, 1);
} else
#endif /* defined(HAVE_PRI_CALL_WAITING) */
{
/* Should the picked channel be used exclusively? */
if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
exclusive = 1;
} else {
exclusive = 0;
}
pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
}
pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
(p->digital ? -1 : layer1));
if (p->pri->facilityenable)
pri_facility_enable(p->pri->pri);
ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
dp_strip = 0;
pridialplan = p->pri->dialplan - 1;
if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->internationalprefix);
}
pridialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->nationalprefix);
}
pridialplan = PRI_NATIONAL_ISDN;
} else {
pridialplan = PRI_LOCAL_ISDN;
}
}
while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
switch (c[p->stripmsd]) {
case 'U':
pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
break;
case 'I':
pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
break;
case 'N':
pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
break;
case 'L':
pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
break;
case 'S':
pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
break;
case 'V':
pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
break;
case 'R':
pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
break;
case 'u':
pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
break;
case 'e':
pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
break;
case 'x':
pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
break;
case 'f':
pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
break;
case 'n':
pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
break;
case 'p':
pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
break;
case 'r':
pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
break;
default:
if (isalpha(c[p->stripmsd])) {
ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
}
break;
}
c++;
}
#if defined(HAVE_PRI_SETUP_KEYPAD)
if (ast_test_flag(&opts, OPT_KEYPAD)
&& !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
/* We have a keypad facility digits option with digits. */
keypad = opt_args[OPT_ARG_KEYPAD];
pri_sr_set_keypad_digits(sr, keypad);
} else {
keypad = NULL;
}
if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
{
pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
}
#if defined(HAVE_PRI_SUBADDR)
if (dialed_subaddress.valid) {
struct pri_party_subaddress subaddress;
memset(&subaddress, 0, sizeof(subaddress));
sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
pri_sr_set_called_subaddress(sr, &subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
#if defined(HAVE_PRI_REVERSE_CHARGE)
if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
}
#endif /* defined(HAVE_PRI_REVERSE_CHARGE) */
#if defined(HAVE_PRI_AOC_EVENTS)
if (ast_test_flag(&opts, OPT_AOC_REQUEST)
&& !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
}
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'd')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_D);
}
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'e')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_E);
}
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
/* Setup the user tag for party id's from this device for this call. */
if (p->pri->append_msn_to_user_tag) {
snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
p->pri->nodetype == PRI_NETWORK
? c + p->stripmsd + dp_strip
: S_COR(ast->connected.id.number.valid,
ast->connected.id.number.str, ""));
} else {
ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
}
/*
* Replace the caller id tag from the channel creation
* with the actual tag value.
*/
ast_free(ast->caller.id.tag);
ast->caller.id.tag = ast_strdup(p->user_tag);
ldp_strip = 0;
prilocaldialplan = p->pri->localdialplan - 1;
if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->internationalprefix);
}
prilocaldialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->nationalprefix);
}
prilocaldialplan = PRI_NATIONAL_ISDN;
} else {
prilocaldialplan = PRI_LOCAL_ISDN;
}
}
if (l != NULL) {
while (*l > '9' && *l != '*' && *l != '#') {
switch (*l) {
case 'U':
prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
break;
case 'I':
prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'N':
prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'L':
prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
break;
case 'S':
prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
break;
case 'V':
prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
break;
case 'R':
prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
break;
case 'u':
prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
break;
case 'e':
prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
break;
case 'x':
prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
break;
case 'f':
prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
break;
case 'n':
prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
break;
case 'p':
prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
break;
case 'r':
prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
break;
default:
if (isalpha(*l)) {
ast_log(LOG_WARNING,
"Unrecognized prilocaldialplan %s modifier: %c\n",
*l > 'Z' ? "NPI" : "TON", *l);
}
break;
}
l++;
}
}
pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
p->use_callingpres ? ast->connected.id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
#if defined(HAVE_PRI_SUBADDR)
if (ast->connected.id.subaddress.valid) {
struct pri_party_subaddress subaddress;
memset(&subaddress, 0, sizeof(subaddress));
sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
pri_sr_set_caller_subaddress(sr, &subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
sig_pri_redirecting_update(p, ast);
#ifdef SUPPORT_USERUSER
/* User-user info */
useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
if (useruser)
pri_sr_set_useruser(sr, useruser);
#endif
#if defined(HAVE_PRI_CCSS)
if (ast_cc_is_recall(ast, &core_id, sig_pri_cc_type_name)) {
struct ast_cc_monitor *monitor;
char device_name[AST_CHANNEL_NAME];
/* This is a CC recall call. */
ast_channel_get_device_name(ast, device_name, sizeof(device_name));
monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
if (monitor) {
struct sig_pri_cc_monitor_instance *instance;
instance = monitor->private_data;
/* If this fails then we have monitor instance ambiguity. */
ast_assert(p->pri == instance->pri);
if (pri_cc_call(p->pri->pri, instance->cc_id, p->call, sr)) {
/* The CC recall call failed for some reason. */
ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
device_name);
ao2_ref(monitor, -1);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
pri_sr_free(sr);
return -1;
}
ao2_ref(monitor, -1);
} else {
core_id = -1;
}
} else
#endif /* defined(HAVE_PRI_CCSS) */
{
core_id = -1;
}
if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
pri_sr_free(sr);
return -1;
}
p->call_level = SIG_PRI_CALL_LEVEL_SETUP;
pri_sr_free(sr);
ast_setstate(ast, AST_STATE_DIALING);
sig_pri_set_dialing(p, 1);
pri_rel(p->pri);
return 0;
}
| int sig_pri_cc_agent_callee_available | ( | struct ast_cc_agent * | agent | ) |
| void sig_pri_cc_agent_destructor | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_agent_init | ( | struct ast_cc_agent * | agent, |
| struct sig_pri_chan * | pvt_chan | ||
| ) |
| int sig_pri_cc_agent_party_b_free | ( | struct ast_cc_agent * | agent | ) |
| void sig_pri_cc_agent_req_rsp | ( | struct ast_cc_agent * | agent, |
| enum ast_cc_agent_response_reason | reason | ||
| ) |
| int sig_pri_cc_agent_start_monitoring | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_agent_start_offer_timer | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_agent_status_req | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_agent_stop_offer_timer | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_agent_stop_ringing | ( | struct ast_cc_agent * | agent | ) |
| int sig_pri_cc_monitor_cancel_available_timer | ( | struct ast_cc_monitor * | monitor, |
| int * | sched_id | ||
| ) |
| void sig_pri_cc_monitor_destructor | ( | void * | monitor_pvt | ) |
| int sig_pri_cc_monitor_req_cc | ( | struct ast_cc_monitor * | monitor, |
| int * | available_timer_id | ||
| ) |
| int sig_pri_cc_monitor_status_rsp | ( | struct ast_cc_monitor * | monitor, |
| enum ast_device_state | devstate | ||
| ) |
| int sig_pri_cc_monitor_suspend | ( | struct ast_cc_monitor * | monitor | ) |
| int sig_pri_cc_monitor_unsuspend | ( | struct ast_cc_monitor * | monitor | ) |
| void sig_pri_chan_alarm_notify | ( | struct sig_pri_chan * | p, |
| int | noalarm | ||
| ) |
Notify new alarm status.
| p | Channel private pointer. |
| noalarm | Non-zero if not in alarm mode. |
Definition at line 7618 of file sig_pri.c.
References pri_grab(), sig_pri_chan::pri, sig_pri_set_alarm(), sig_pri_span::pri, sig_pri_chan::call, sig_pri_chan::owner, ast_channel::_softhangup, AST_SOFTHANGUP_DEV, sig_pri_span_devstate_changed(), and pri_rel().
Referenced by dahdi_handle_event(), and handle_init_event().
{
pri_grab(p, p->pri);
sig_pri_set_alarm(p, !noalarm);
if (!noalarm) {
if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
/* T309 is not enabled : destroy calls when alarm occurs */
if (p->call) {
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
}
if (p->owner)
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
}
sig_pri_span_devstate_changed(p->pri);
pri_rel(p->pri);
}
| void sig_pri_chan_delete | ( | struct sig_pri_chan * | doomed | ) |
Delete the sig_pri private channel structure.
| doomed | sig_pri private channel structure to delete. |
Definition at line 7665 of file sig_pri.c.
References ast_free.
Referenced by destroy_dahdi_pvt().
{
ast_free(doomed);
}
| struct sig_pri_chan* sig_pri_chan_new | ( | void * | pvt_data, |
| struct sig_pri_callback * | callback, | ||
| struct sig_pri_span * | pri, | ||
| int | logicalspan, | ||
| int | channo, | ||
| int | trunkgroup | ||
| ) | [read] |
Definition at line 7637 of file sig_pri.c.
References ast_calloc, sig_pri_chan::logicalspan, sig_pri_chan::prioffset, sig_pri_chan::mastertrunkgroup, sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_chan::pri.
Referenced by mkintf(), and dahdi_new_pri_nobch_channel().
{
struct sig_pri_chan *p;
p = ast_calloc(1, sizeof(*p));
if (!p)
return p;
p->logicalspan = logicalspan;
p->prioffset = channo;
p->mastertrunkgroup = trunkgroup;
p->calls = callback;
p->chan_pvt = pvt_data;
p->pri = pri;
return p;
}
| void sig_pri_cli_show_channels | ( | int | fd, |
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 7678 of file sig_pri.c.
References ast_mutex_lock, sig_pri_span::lock, sig_pri_span::numchans, sig_pri_span::pvts, sig_pri_lock_private(), sig_pri_lock_owner(), sig_pri_chan::no_b_channel, sig_pri_is_chan_available(), sig_pri_unlock_private(), SIG_PRI_SC_LINE, sig_pri_span::span, sig_pri_chan::channel, sig_pri_call_level2str(), sig_pri_chan::call_level, sig_pri_chan::call, sig_pri_chan::owner, ast_channel::name, ast_channel_unlock, ast_mutex_unlock, and ast_cli().
Referenced by handle_pri_show_channels().
{
char line[256];
int idx;
struct sig_pri_chan *pvt;
ast_mutex_lock(&pri->lock);
for (idx = 0; idx < pri->numchans; ++idx) {
if (!pri->pvts[idx]) {
continue;
}
pvt = pri->pvts[idx];
sig_pri_lock_private(pvt);
sig_pri_lock_owner(pri, idx);
if (pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
/* Don't show held/call-waiting channels if they are not in use. */
sig_pri_unlock_private(pvt);
continue;
}
snprintf(line, sizeof(line), SIG_PRI_SC_LINE,
pri->span,
pvt->channel,
pvt->no_b_channel ? "No" : "Yes",/* Has media */
sig_pri_is_chan_available(pvt) ? "Yes" : "No",
sig_pri_call_level2str(pvt->call_level),
pvt->call ? "Yes" : "No",
pvt->owner ? pvt->owner->name : "");
if (pvt->owner) {
ast_channel_unlock(pvt->owner);
}
sig_pri_unlock_private(pvt);
ast_mutex_unlock(&pri->lock);
ast_cli(fd, "%s\n", line);
ast_mutex_lock(&pri->lock);
}
ast_mutex_unlock(&pri->lock);
}
| void sig_pri_cli_show_channels_header | ( | int | fd | ) |
Definition at line 7672 of file sig_pri.c.
References ast_cli(), and SIG_PRI_SC_HEADER.
Referenced by handle_pri_show_channels().
{
ast_cli(fd, SIG_PRI_SC_HEADER, "PRI", "", "B", "Chan", "Call", "PRI", "Channel");
ast_cli(fd, SIG_PRI_SC_HEADER, "Span", "Chan", "Chan", "Idle", "Level", "Call", "Name");
}
| void sig_pri_cli_show_span | ( | int | fd, |
| int * | dchannels, | ||
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 7750 of file sig_pri.c.
References status, SIG_PRI_NUM_DCHANS, sig_pri_span::dchans, ast_cli(), pri_order(), build_status(), sig_pri_span::dchanavail, sig_pri_span::pri, ast_mutex_lock, sig_pri_span::lock, free, ast_mutex_unlock, sig_pri_span::overlapdial, and DAHDI_OVERLAPDIAL_INCOMING.
Referenced by handle_pri_show_span().
{
int x;
char status[256];
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchans[x]) {
#ifdef PRI_DUMP_INFO_STR
char *info_str = NULL;
#endif
ast_cli(fd, "%s D-channel: %d\n", pri_order(x), dchannels[x]);
build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
ast_cli(fd, "Status: %s\n", status);
ast_mutex_lock(&pri->lock);
#ifdef PRI_DUMP_INFO_STR
info_str = pri_dump_info_str(pri->pri);
if (info_str) {
ast_cli(fd, "%s", info_str);
free(info_str);
}
#else
pri_dump_info(pri->pri);
#endif
ast_mutex_unlock(&pri->lock);
ast_cli(fd, "Overlap Recv: %s\n\n", (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
ast_cli(fd, "\n");
}
}
}
| void sig_pri_cli_show_spans | ( | int | fd, |
| int | span, | ||
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 7738 of file sig_pri.c.
References status, SIG_PRI_NUM_DCHANS, sig_pri_span::dchans, build_status(), sig_pri_span::dchanavail, sig_pri_span::pri, and ast_cli().
Referenced by handle_pri_show_spans().
{
char status[256];
int x;
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchans[x]) {
build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
ast_cli(fd, "PRI span %d/%d: %s\n", span, x, status);
}
}
}
| int sig_pri_digit_begin | ( | struct sig_pri_chan * | pvt, |
| struct ast_channel * | ast, | ||
| char | digit | ||
| ) |
Definition at line 7215 of file sig_pri.c.
References ast_channel::_state, AST_STATE_DIALING, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_OVERLAP, len(), sig_pri_chan::dialdest, ast_debug, ast_log(), LOG_WARNING, sig_pri_chan::pri, sig_pri_span::span, SIG_PRI_CALL_LEVEL_PROCEEDING, pri_grab(), sig_pri_span::pri, sig_pri_chan::call, pri_rel(), SIG_PRI_CALL_LEVEL_CONNECT, and sig_pri_call_level2str().
Referenced by dahdi_digit_begin().
{
if (ast->_state == AST_STATE_DIALING) {
if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
unsigned int len;
len = strlen(pvt->dialdest);
if (len < sizeof(pvt->dialdest) - 1) {
ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
digit);
pvt->dialdest[len++] = digit;
pvt->dialdest[len] = '\0';
} else {
ast_log(LOG_WARNING,
"Span %d: Deferred digit buffer overflow for digit '%c'.\n",
pvt->pri->span, digit);
}
return 0;
}
if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
if (!pri_grab(pvt, pvt->pri)) {
pri_information(pvt->pri->pri, pvt->call, digit);
pri_rel(pvt->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->pri->span);
}
return 0;
}
if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
ast_log(LOG_WARNING,
"Span %d: Digit '%c' may be ignored by peer. (Call level:%d(%s))\n",
pvt->pri->span, digit, pvt->call_level,
sig_pri_call_level2str(pvt->call_level));
}
}
return 1;
}
| void sig_pri_extract_called_num_subaddr | ( | struct sig_pri_chan * | p, |
| const char * | rdest, | ||
| char * | called, | ||
| size_t | called_buff_size | ||
| ) |
Extract the called number and subaddress from the dial string.
| p | sig_pri channel structure. |
| rdest | Dial string buffer to extract called number and subaddress. |
| called | Buffer to fill with extracted <number>[:<subaddress>] |
| called_buff_size | Size of buffer to fill. |
Definition at line 6321 of file sig_pri.c.
References AST_DECLARE_APP_ARGS, args, AST_APP_ARG, ext, ast_strdupa, AST_NONSTANDARD_APP_ARGS, sig_pri_chan::stripmsd, and ast_strlen_zero().
Referenced by dahdi_request().
{
char *dial;
char *number;
char *subaddr;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(group); /* channel/group token */
AST_APP_ARG(ext); /* extension token */
//AST_APP_ARG(opts); /* options token */
AST_APP_ARG(other); /* Any remining unused arguments */
);
/* Get private copy of dial string and break it up. */
dial = ast_strdupa(rdest);
AST_NONSTANDARD_APP_ARGS(args, dial, '/');
number = args.ext;
if (!number) {
number = "";
}
/* Find and extract dialed_subaddress */
subaddr = strchr(number, ':');
if (subaddr) {
*subaddr++ = '\0';
/* Skip subaddress type prefix. */
switch (*subaddr) {
case 'U':
case 'u':
case 'N':
case 'n':
++subaddr;
break;
default:
break;
}
}
/* Skip type-of-number/dial-plan prefix characters. */
if (strlen(number) < p->stripmsd) {
number = "";
} else {
number += p->stripmsd;
while (isalpha(*number)) {
++number;
}
}
/* Fill buffer with extracted number and subaddress. */
if (ast_strlen_zero(subaddr)) {
/* Put in called number only since there is no subaddress. */
snprintf(called, called_buff_size, "%s", number);
} else {
/* Put in called number and subaddress. */
snprintf(called, called_buff_size, "%s:%s", number, subaddr);
}
}
| void sig_pri_fixup | ( | struct ast_channel * | oldchan, |
| struct ast_channel * | newchan, | ||
| struct sig_pri_chan * | pchan | ||
| ) |
Definition at line 7838 of file sig_pri.c.
References sig_pri_chan::owner.
Referenced by dahdi_fixup().
| int sig_pri_hangup | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast | ||
| ) |
Definition at line 6226 of file sig_pri.c.
References pbx_builtin_getvar_helper(), ast_log(), LOG_DEBUG, sig_pri_chan::channel, ast_channel::tech_pvt, LOG_WARNING, sig_pri_chan::outgoing, sig_pri_set_digital(), ast_atomic_fetchadd_int(), sig_pri_chan::pri, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_IDLE, sig_pri_chan::progress, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::cid_name, sig_pri_chan::user_tag, sig_pri_chan::exten, sig_pri_set_dialing(), pri_grab(), sig_pri_chan::call, sig_pri_chan::alreadyhungup, sig_pri_span::pri, cause, ast_channel::hangupcause, sig_pri_chan::allocated, sig_pri_chan::owner, sig_pri_span_devstate_changed(), and pri_rel().
Referenced by dahdi_hangup().
{
#ifdef SUPPORT_USERUSER
const char *useruser = pbx_builtin_getvar_helper(ast, "USERUSERINFO");
#endif
ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
if (!ast->tech_pvt) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
p->outgoing = 0;
sig_pri_set_digital(p, 0); /* push up to parent for EC*/
#if defined(HAVE_PRI_CALL_WAITING)
if (p->is_call_waiting) {
p->is_call_waiting = 0;
ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
p->call_level = SIG_PRI_CALL_LEVEL_IDLE;
p->progress = 0;
p->cid_num[0] = '\0';
p->cid_subaddr[0] = '\0';
p->cid_name[0] = '\0';
p->user_tag[0] = '\0';
p->exten[0] = '\0';
sig_pri_set_dialing(p, 0);
/* Make sure we have a call (or REALLY have a call in the case of a PRI) */
pri_grab(p, p->pri);
if (p->call) {
if (p->alreadyhungup) {
ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
#endif
#if defined(HAVE_PRI_AOC_EVENTS)
if (p->holding_aoce) {
pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
pri_hangup(p->pri->pri, p->call, -1);
p->call = NULL;
} else {
const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
int icause = ast->hangupcause ? ast->hangupcause : -1;
ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
#endif
p->alreadyhungup = 1;
if (cause) {
if (atoi(cause))
icause = atoi(cause);
}
#if defined(HAVE_PRI_AOC_EVENTS)
if (p->holding_aoce) {
pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
pri_hangup(p->pri->pri, p->call, icause);
}
}
#if defined(HAVE_PRI_AOC_EVENTS)
p->aoc_s_request_invoke_id_valid = 0;
p->holding_aoce = 0;
p->waiting_for_aoce = 0;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
p->allocated = 0;
p->owner = NULL;
sig_pri_span_devstate_changed(p->pri);
pri_rel(p->pri);
return 0;
}
| int sig_pri_indicate | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | chan, | ||
| int | condition, | ||
| const void * | data, | ||
| size_t | datalen | ||
| ) |
Definition at line 6834 of file sig_pri.c.
References AST_CONTROL_BUSY, sig_pri_chan::priindication_oob, sig_pri_chan::no_b_channel, ast_channel::hangupcause, AST_CAUSE_USER_BUSY, ast_channel::_softhangup, AST_SOFTHANGUP_DEV, sig_pri_play_tone(), SIG_PRI_TONE_BUSY, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_ALERTING, sig_pri_chan::outgoing, sig_pri_chan::progress, sig_pri_chan::pri, sig_pri_span::pri, pri_grab(), sig_pri_chan::call, PVT_TO_CHANNEL(), pri_rel(), ast_log(), LOG_WARNING, sig_pri_span::span, AST_CONTROL_RINGING, sig_pri_chan::digital, SIG_PRI_TONE_RINGTONE, ast_channel::_state, AST_STATE_UP, AST_STATE_RING, ast_setstate(), AST_STATE_RINGING, AST_CONTROL_PROCEEDING, ast_debug, ast_channel::name, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_set_dialing(), AST_CONTROL_PROGRESS, sig_pri_set_digital(), AST_CONTROL_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_SWITCH_CONGESTION, SIG_PRI_TONE_CONGESTION, AST_CONTROL_HOLD, sig_pri_chan::mohinterpret, sig_pri_chan::prioffset, ast_moh_start(), AST_CONTROL_UNHOLD, ast_moh_stop(), AST_CONTROL_SRCUPDATE, AST_CONTROL_CONNECTED_LINE, sig_pri_party_id_from_ast(), ast_channel::connected, ast_party_connected_line::id, AST_CONTROL_REDIRECTING, sig_pri_redirecting_update(), AST_CONTROL_AOC, ast_aoc_decode(), ast_aoc_get_msg_type(), AST_AOC_S, SIG_PRI_AOC_GRANT_S, AST_AOC_D, SIG_PRI_AOC_GRANT_D, AST_AOC_E, SIG_PRI_AOC_GRANT_E, LOG_DEBUG, ast_softhangup_nolock(), AST_AOC_REQUEST, ast_aoc_get_termination_request(), and ast_aoc_destroy_decoded().
Referenced by dahdi_indicate().
{
int res = -1;
switch (condition) {
case AST_CONTROL_BUSY:
if (p->priindication_oob || p->no_b_channel) {
chan->hangupcause = AST_CAUSE_USER_BUSY;
chan->_softhangup |= AST_SOFTHANGUP_DEV;
res = 0;
break;
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY);
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
chan->hangupcause = AST_CAUSE_USER_BUSY;
p->progress = 1;/* No need to send plain PROGRESS after this. */
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
}
}
break;
case AST_CONTROL_RINGING:
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
p->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
p->no_b_channel || p->digital ? 0 : 1);
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
}
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE);
if (chan->_state != AST_STATE_UP) {
if (chan->_state != AST_STATE_RING)
ast_setstate(chan, AST_STATE_RINGING);
}
break;
case AST_CONTROL_PROCEEDING:
ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
p->no_b_channel || p->digital ? 0 : 1);
if (!p->no_b_channel && !p->digital) {
sig_pri_set_dialing(p, 0);
}
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
}
}
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_PROGRESS:
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing
&& !p->no_b_channel) {
p->progress = 1;/* No need to send plain PROGRESS again. */
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
}
}
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_CONGESTION:
if (p->priindication_oob || p->no_b_channel) {
/* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
switch (chan->hangupcause) {
case AST_CAUSE_USER_BUSY:
case AST_CAUSE_NORMAL_CLEARING:
case 0:/* Cause has not been set. */
/* Supply a more appropriate cause. */
chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
break;
default:
break;
}
chan->_softhangup |= AST_SOFTHANGUP_DEV;
res = 0;
break;
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION);
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
/* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
switch (chan->hangupcause) {
case AST_CAUSE_USER_BUSY:
case AST_CAUSE_NORMAL_CLEARING:
case 0:/* Cause has not been set. */
/* Supply a more appropriate cause. */
chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
break;
default:
break;
}
p->progress = 1;/* No need to send plain PROGRESS after this. */
if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
}
}
break;
case AST_CONTROL_HOLD:
if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
if (!pri_grab(p, p->pri)) {
res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
}
} else
ast_moh_start(chan, data, p->mohinterpret);
break;
case AST_CONTROL_UNHOLD:
if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
if (!pri_grab(p, p->pri)) {
res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
pri_rel(p->pri);
}
} else
ast_moh_stop(chan);
break;
case AST_CONTROL_SRCUPDATE:
res = 0;
break;
case -1:
res = sig_pri_play_tone(p, -1);
break;
case AST_CONTROL_CONNECTED_LINE:
ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", chan->name);
if (p->pri && !pri_grab(p, p->pri)) {
struct pri_party_connected_line connected;
memset(&connected, 0, sizeof(connected));
sig_pri_party_id_from_ast(&connected.id, &chan->connected.id);
pri_connected_line_update(p->pri->pri, p->call, &connected);
pri_rel(p->pri);
}
break;
case AST_CONTROL_REDIRECTING:
ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", chan->name);
if (p->pri && !pri_grab(p, p->pri)) {
sig_pri_redirecting_update(p, chan);
pri_rel(p->pri);
}
break;
case AST_CONTROL_AOC:
#if defined(HAVE_PRI_AOC_EVENTS)
{
struct ast_aoc_decoded *decoded
= ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
ast_debug(1, "Received AST_CONTROL_AOC on %s\n", chan->name);
if (decoded && p->pri && !pri_grab(p, p->pri)) {
switch (ast_aoc_get_msg_type(decoded)) {
case AST_AOC_S:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
sig_pri_aoc_s_from_ast(p, decoded);
}
break;
case AST_AOC_D:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
sig_pri_aoc_d_from_ast(p, decoded);
}
break;
case AST_AOC_E:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
sig_pri_aoc_e_from_ast(p, decoded);
}
/* if hangup was delayed for this AOC-E msg, waiting_for_aoc
* will be set. A hangup is already occuring via a timeout during
* this delay. Instead of waiting for that timeout to occur, go ahead
* and initiate the softhangup since the delay is no longer necessary */
if (p->waiting_for_aoce) {
p->waiting_for_aoce = 0;
ast_log(LOG_DEBUG,
"Received final AOC-E msg, continue with hangup on %s\n",
chan->name);
ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
}
break;
case AST_AOC_REQUEST:
/* We do not pass through AOC requests, So unless this
* is an AOC termination request it will be ignored */
if (ast_aoc_get_termination_request(decoded)) {
pri_hangup(p->pri->pri, p->call, -1);
}
break;
default:
break;
}
pri_rel(p->pri);
}
ast_aoc_destroy_decoded(decoded);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
break;
}
return res;
}
| void sig_pri_init_pri | ( | struct sig_pri_span * | pri | ) |
Definition at line 6213 of file sig_pri.c.
References ast_mutex_init, sig_pri_span::lock, sig_pri_span::master, AST_PTHREADT_NULL, SIG_PRI_NUM_DCHANS, and sig_pri_span::fds.
Referenced by dahdi_restart(), and load_module().
{
int i;
memset(pri, 0, sizeof(*pri));
ast_mutex_init(&pri->lock);
pri->master = AST_PTHREADT_NULL;
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++)
pri->fds[i] = -1;
}
| int sig_pri_is_chan_available | ( | struct sig_pri_chan * | pvt | ) |
Determine if a private channel structure is available.
| pvt | Channel to determine if available. |
Definition at line 1090 of file sig_pri.c.
References sig_pri_is_chan_in_use().
Referenced by dahdi_pri_update_span_devstate(), pri_fixup_principle(), pri_find_empty_chan(), pri_dchannel(), sig_pri_available_check(), and sig_pri_cli_show_channels().
{
return !sig_pri_is_chan_in_use(pvt)
#if defined(HAVE_PRI_SERVICE_MESSAGES)
/* And not out-of-service */
&& !pvt->service_status
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
;
}
| int sig_pri_load | ( | const char * | cc_type_name | ) |
Load the sig_pri submodule.
| cc_type_name | CC type name to use when looking up agent/monitor. |
| 0 | on success. |
| -1 | on error. |
Definition at line 8450 of file sig_pri.c.
References ao2_container_alloc.
Referenced by load_module().
{
#if defined(HAVE_PRI_CCSS)
sig_pri_cc_type_name = cc_type_name;
sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn,
sig_pri_cc_monitor_instance_cmp_fn);
if (!sig_pri_cc_monitors) {
return -1;
}
#endif /* defined(HAVE_PRI_CCSS) */
return 0;
}
| struct ast_channel* sig_pri_request | ( | struct sig_pri_chan * | p, |
| enum sig_pri_law | law, | ||
| const struct ast_channel * | requestor, | ||
| int | transfercapability | ||
| ) | [read] |
Definition at line 981 of file sig_pri.c.
References ast_log(), LOG_DEBUG, sig_pri_chan::channel, sig_pri_chan::outgoing, sig_pri_new_ast_channel(), AST_STATE_RESERVED, and sig_pri_chan::exten.
Referenced by dahdi_request(), and pri_dchannel().
{
struct ast_channel *ast;
ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
p->outgoing = 1;
ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
if (!ast) {
p->outgoing = 0;
}
return ast;
}
| void sig_pri_set_alarm | ( | struct sig_pri_chan * | p, |
| int | in_alarm | ||
| ) |
Definition at line 181 of file sig_pri.c.
References sig_pri_chan::resetting, sig_pri_chan::inalarm, sig_pri_chan::calls, sig_pri_callback::set_alarm, and sig_pri_chan::chan_pvt.
Referenced by mkintf(), pri_dchannel(), and sig_pri_chan_alarm_notify().
| int sig_pri_start_pri | ( | struct sig_pri_span * | pri | ) |
Definition at line 7427 of file sig_pri.c.
References ast_str_alloca, ARRAY_LEN, ast_event_unsubscribe(), ast_mutex_init, sig_pri_span::lock, sig_pri_sort_pri_chans(), strsep(), ast_strip(), ast_strlen_zero(), ast_str_set(), sig_pri_span::span, ast_event_subscribe(), AST_EVENT_MWI, ast_str_buffer(), AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, ast_log(), LOG_ERROR, SIG_PRI_NUM_DCHANS, sig_pri_span::fds, sig_pri_span::sig, SIG_BRI, sig_pri_span::dchans, sig_pri_span::nodetype, sig_pri_span::switchtype, SIG_BRI_PTMP, sig_pri_span::overlapdial, DAHDI_OVERLAPDIAL_OUTGOING, sig_pri_span::qsigchannelmapping, DAHDI_CHAN_MAPPING_LOGICAL, SIG_PRI_DEBUG_DEFAULT, sig_pri_span::nsf, sig_pri_span::pritimers, sig_pri_span::pri, sig_pri_span::resetpos, ast_pthread_create_background, sig_pri_span::master, pri_dchannel(), and errno.
Referenced by setup_dahdi_int().
{
int x;
int i;
#if defined(HAVE_PRI_MWI)
char *saveptr;
char *mbox_number;
char *mbox_context;
struct ast_str *mwi_description = ast_str_alloca(64);
#endif /* defined(HAVE_PRI_MWI) */
#if defined(HAVE_PRI_MWI)
/* Prepare the mbox[] for use. */
for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
if (pri->mbox[i].sub) {
pri->mbox[i].sub = ast_event_unsubscribe(pri->mbox[i].sub);
}
}
#endif /* defined(HAVE_PRI_MWI) */
ast_mutex_init(&pri->lock);
sig_pri_sort_pri_chans(pri);
#if defined(HAVE_PRI_MWI)
/*
* Split the mwi_mailboxes configuration string into the mbox[]:
* mailbox_number[@context]{,mailbox_number[@context]}
*/
i = 0;
saveptr = pri->mwi_mailboxes;
while (i < ARRAY_LEN(pri->mbox)) {
mbox_number = strsep(&saveptr, ",");
if (!mbox_number) {
break;
}
/* Split the mailbox_number and context */
mbox_context = strchr(mbox_number, '@');
if (mbox_context) {
*mbox_context++ = '\0';
mbox_context = ast_strip(mbox_context);
}
mbox_number = ast_strip(mbox_number);
if (ast_strlen_zero(mbox_number)) {
/* There is no mailbox number. Skip it. */
continue;
}
if (ast_strlen_zero(mbox_context)) {
/* There was no context so use the default. */
mbox_context = "default";
}
/* Fill the mbox[] element. */
ast_str_set(&mwi_description, -1, "%s span %d[%d] MWI mailbox %s@%s",
sig_pri_cc_type_name, pri->span, i, mbox_number, mbox_context);
pri->mbox[i].sub = ast_event_subscribe(AST_EVENT_MWI, sig_pri_mwi_event_cb,
ast_str_buffer(mwi_description), pri,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox_number,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mbox_context,
AST_EVENT_IE_END);
if (!pri->mbox[i].sub) {
ast_log(LOG_ERROR, "%s span %d could not subscribe to MWI events for %s@%s.",
sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
continue;
}
pri->mbox[i].number = mbox_number;
pri->mbox[i].context = mbox_context;
++i;
}
#endif /* defined(HAVE_PRI_MWI) */
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (pri->fds[i] == -1) {
break;
}
switch (pri->sig) {
case SIG_BRI:
pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
break;
case SIG_BRI_PTMP:
pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
break;
default:
pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
#if defined(HAVE_PRI_SERVICE_MESSAGES)
if (pri->enable_service_message_support) {
pri_set_service_message_support(pri->dchans[i], 1);
}
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
break;
}
pri_set_overlapdial(pri->dchans[i], (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) ? 1 : 0);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
#endif
#ifdef HAVE_PRI_INBANDDISCONNECT
pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
#endif
/* Enslave to master if appropriate */
if (i)
pri_enslave(pri->dchans[0], pri->dchans[i]);
if (!pri->dchans[i]) {
if (pri->fds[i] > 0)
close(pri->fds[i]);
pri->fds[i] = -1;
ast_log(LOG_ERROR, "Unable to create PRI structure\n");
return -1;
}
pri_set_debug(pri->dchans[i], SIG_PRI_DEBUG_DEFAULT);
pri_set_nsf(pri->dchans[i], pri->nsf);
#ifdef PRI_GETSET_TIMERS
for (x = 0; x < PRI_MAX_TIMERS; x++) {
if (pri->pritimers[x] != 0)
pri_set_timer(pri->dchans[i], x, pri->pritimers[x]);
}
#endif
}
/* Assume primary is the one we use */
pri->pri = pri->dchans[0];
#if defined(HAVE_PRI_CALL_HOLD)
pri_hold_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_REROUTING)
pri_reroute_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_REROUTING) */
#if defined(HAVE_PRI_HANGUP_FIX)
pri_hangup_fix_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_HANGUP_FIX) */
#if defined(HAVE_PRI_CCSS)
pri_cc_enable(pri->pri, 1);
pri_cc_recall_mode(pri->pri, pri->cc_ptmp_recall_mode);
pri_cc_retain_signaling_req(pri->pri, pri->cc_qsig_signaling_link_req);
pri_cc_retain_signaling_rsp(pri->pri, pri->cc_qsig_signaling_link_rsp);
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_TRANSFER)
pri_transfer_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_TRANSFER) */
#if defined(HAVE_PRI_AOC_EVENTS)
pri_aoc_events_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_CALL_WAITING)
pri_connect_ack_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_WAITING) */
#if defined(HAVE_PRI_MCID)
pri_mcid_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_L2_PERSISTENCE)
pri_persistent_layer2_option(pri->pri, pri->l2_persistence);
#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
pri->resetpos = -1;
if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (!pri->dchans[i])
break;
if (pri->fds[i] > 0)
close(pri->fds[i]);
pri->fds[i] = -1;
}
ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
return -1;
}
#if defined(HAVE_PRI_MWI)
/*
* Send the initial MWI indications from the event cache for this span.
*
* If we were loaded after app_voicemail the event would already be in
* the cache. If we were loaded before app_voicemail the event would not
* be in the cache yet and app_voicemail will send the event when it
* gets loaded.
*/
sig_pri_mwi_cache_update(pri);
#endif /* defined(HAVE_PRI_MWI) */
return 0;
}
| void sig_pri_stop_pri | ( | struct sig_pri_span * | pri | ) |
Stop PRI span.
| pri | PRI span control structure. |
Definition at line 7362 of file sig_pri.c.
References ARRAY_LEN, and ast_event_unsubscribe().
Referenced by __unload_module().
{
#if defined(HAVE_PRI_MWI)
int idx;
#endif /* defined(HAVE_PRI_MWI) */
#if defined(HAVE_PRI_MWI)
for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
if (pri->mbox[idx].sub) {
pri->mbox[idx].sub = ast_event_unsubscribe(pri->mbox[idx].sub);
}
}
#endif /* defined(HAVE_PRI_MWI) */
}
| void sig_pri_unload | ( | void | ) |
Unload the sig_pri submodule.
Definition at line 8469 of file sig_pri.c.
References ao2_ref.
Referenced by __unload_module().
{
#if defined(HAVE_PRI_CCSS)
if (sig_pri_cc_monitors) {
ao2_ref(sig_pri_cc_monitors, -1);
sig_pri_cc_monitors = NULL;
}
#endif /* defined(HAVE_PRI_CCSS) */
}