[asterisk-commits] rmudgett: branch group/issue14292 r169783 - /team/group/issue14292/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jan 21 15:30:40 CST 2009
Author: rmudgett
Date: Wed Jan 21 15:30:40 2009
New Revision: 169783
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=169783
Log:
Applied the asterisk-issue8824-2008-12-10-ccbsccnr-0.1.0.patch
to the new team/group/issue14292 branched from the team/group/issue14068 branch.
(issue 0014292)
Modified:
team/group/issue14292/channels/chan_dahdi.c
Modified: team/group/issue14292/channels/chan_dahdi.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/issue14292/channels/chan_dahdi.c?view=diff&rev=169783&r1=169782&r2=169783
==============================================================================
--- team/group/issue14292/channels/chan_dahdi.c (original)
+++ team/group/issue14292/channels/chan_dahdi.c Wed Jan 21 15:30:40 2009
@@ -335,6 +335,296 @@
* knows that we care about it. Then, chan_dahdi will get the MWI from the
* event cache instead of checking the mailbox directly. */
}
+
+#ifdef HAVE_PRI
+#define CC_TIMEOUT_PEERLINKCHANNELS 60
+#define CC_MAX_PEERLINKCHANNELS 20*CC_TIMEOUT_PEERLINKCHANNELS
+AST_MUTEX_DEFINE_STATIC(peerlink_lock);
+static struct peerlink_s {
+ struct ast_channel *channel;
+ time_t age;
+} peerlinkchannel[CC_MAX_PEERLINKCHANNELS+1];
+
+
+#define CC_IDLE 1
+#define CC_WAIT_ACK 2
+#define CC_INVOKED_A_RET 3
+#define CC_WAIT_USER_A_ANSWER_N 4
+
+#define CCBS_SPAN(h) ((h) & 0xff)
+#define CCBS_CR(h) (((h) >> 16) & 0xffff)
+#define CCBS_HANDLE(s,r) ((s & 0xff) | ((r & 0xffff) << 16))
+
+struct ccbsnr_link {
+ unsigned int handle;
+ char type;
+ unsigned int state;
+ char callingnum[AST_MAX_EXTENSION];
+ char callernum[AST_MAX_EXTENSION];
+ char callername[AST_MAX_EXTENSION];
+ char context[AST_MAX_CONTEXT];
+ int priority;
+ q931_call *call;
+ struct ast_channel *peer;
+ time_t age;
+ struct ccbsnr_link *next;
+};
+
+static struct ccbsnr_link *ccbsnr_list = NULL;
+AST_MUTEX_DEFINE_STATIC(ccbsnr_lock);
+
+/*
+ * remove too old CCBS/CCNR entries
+ * (must be called with ccbsnr_lock held)
+ */
+static void del_old_ccbsnr(void)
+{
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link *tmp = NULL;
+
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ if ((ccbsnr->age + 86400) < time(NULL)) {
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: CCBS/CCNR handle=%d timeout.\n", ccbsnr->handle);
+ if (!tmp) {
+ ccbsnr_list = ccbsnr->next;
+ } else {
+ tmp->next = ccbsnr->next;
+ }
+ ast_free(ccbsnr);
+ break;
+ }
+ tmp = ccbsnr;
+ ccbsnr = ccbsnr->next;
+ }
+}
+
+
+/*
+ * return the pointer to ccbsnr structure by handle
+ */
+static struct ccbsnr_link *ccbsnr_get_link(unsigned int handle, unsigned int *state)
+{
+ struct ccbsnr_link *ret;
+
+ if (state) {
+ *state = CC_IDLE;
+ }
+
+ if (handle)
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: ccbsnr_get_link: handle=%x\n", handle);
+
+ ast_mutex_lock(&ccbsnr_lock);
+
+ ret = ccbsnr_list;
+ while (ret) {
+ if ((handle) && (ret->handle == handle)) {
+ if (state) {
+ *state = ret->state;
+ }
+ break;
+ }
+ ret = ret->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ return ret;
+}
+
+
+static struct ccbsnr_link *ccbsnr_get_link_by_number(const char *callingnum, const char *callernum, unsigned int *state)
+{
+ struct ccbsnr_link *ret;
+
+ if (state) {
+ *state = CC_IDLE;
+ }
+
+ if (callingnum && callernum) {
+ if (strlen(callingnum) && strlen(callernum))
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: ccbsnr_get_link_by_number: callingnum=%s callernum=%s\n", callingnum, callernum);
+ } else {
+ return NULL;
+ }
+
+ ast_mutex_lock(&ccbsnr_lock);
+
+ ret = ccbsnr_list;
+ while (ret) {
+ if (!strcmp(ret->callingnum, callingnum) && !strcmp(ret->callernum, callernum)) {
+ if (state) {
+ *state = ret->state;
+ }
+ break;
+ }
+ ret = ret->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ return ret;
+}
+
+
+/*
+ * select CCBS/CCNR id
+ */
+static struct ccbsnr_link *ccbsnr_select_link(unsigned int handle) {
+
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link * ret = NULL;
+ int ccbsnronprispan;
+ int cr;
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: ccbsnr_select_link: handle=%x\n", handle);
+
+ ast_mutex_lock(&ccbsnr_lock);
+
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ if ((ccbsnr->handle == handle) && (ccbsnr->state == CC_WAIT_ACK)) {
+ ccbsnr->state = CC_INVOKED_A_RET;
+ ret = ccbsnr;
+
+ ccbsnronprispan = CCBS_SPAN(handle);
+ cr = CCBS_CR(handle);
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: request CCBS/NR span=%d type=%d cr =%x handle=%x state=%d (%s, %s, %s, %s, %d)\n",
+ ccbsnronprispan, ccbsnr->type, cr, handle, ccbsnr->state, ccbsnr->callingnum, ccbsnr->callernum, ccbsnr->callername, ccbsnr->context, ccbsnr->priority);
+ break;
+ }
+ ccbsnr = ccbsnr->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ return ret;
+}
+
+
+/*
+ * a CCBS/CCNR link was removed
+ */
+static void ccbsnr_del_link(unsigned int handle)
+{
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link *tmp = NULL;
+ int ccbsnronprispan;
+ int cr;
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: ccbsnr_del_link: handle=%x\n", handle);
+
+ ast_mutex_lock(&ccbsnr_lock);
+
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ if (ccbsnr->handle == handle) {
+ if (!tmp) {
+ ccbsnr_list = ccbsnr->next;
+ } else {
+ tmp->next = ccbsnr->next;
+ }
+ ccbsnronprispan = CCBS_SPAN(handle);
+ cr = CCBS_CR(handle);
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI: destroy CCBS/NR span=%d type=%d cr=%x handle=%x state=%d (%s, %s, %s, %s, %d)\n",
+ ccbsnronprispan, ccbsnr->type, cr, handle, ccbsnr->state, ccbsnr->callingnum, ccbsnr->callernum, ccbsnr->callername, ccbsnr->context, ccbsnr->priority);
+
+ if (ccbsnr->call )
+ ast_log(LOG_NOTICE, "call(%x) must be 'NULL'. Memory leak!\n", (int)ccbsnr->call);
+
+ ast_free(ccbsnr);
+ break;
+ }
+ tmp = ccbsnr;
+ ccbsnr = ccbsnr->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+}
+
+
+/*
+ * return the counter of ccbsnrlinks to callingnumber
+ */
+static int ccbsnr_count_callingnum(const char *callingnum)
+{
+ int count = 0;
+ struct ccbsnr_link *ccbsnr;
+
+ ast_mutex_lock(&ccbsnr_lock);
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ if (!strcmp(ccbsnr->callingnum, callingnum)) {
+ count++;
+ }
+ ccbsnr = ccbsnr->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ return count;
+}
+
+
+/*
+ * Add a new peer link id
+ */
+static int cc_add_peer_link_id(struct ast_channel *ast)
+{
+ int i;
+
+ ast_mutex_lock(&peerlink_lock);
+ for (i = 1; i <= CC_MAX_PEERLINKCHANNELS; i++) {
+ if (peerlinkchannel[i].channel == NULL) {
+ peerlinkchannel[i].channel = ast;
+ peerlinkchannel[i].age = time(NULL);
+ break;
+ } else {
+ /* remove too old entries */
+ if ((peerlinkchannel[i].age + CC_TIMEOUT_PEERLINKCHANNELS) < time(NULL)) {
+ peerlinkchannel[i].channel = NULL;
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDI: peerlink %d timeout-erase\n", i);
+ }
+ }
+ }
+ ast_mutex_unlock(&peerlink_lock);
+ if (i > CC_MAX_PEERLINKCHANNELS) {
+ return -1;
+ }
+ return i;
+}
+
+/*
+ * Get and remove peer link id
+ */
+static struct ast_channel *cc_get_peer_link_id(const char *p)
+{
+ int id = -1;
+ struct ast_channel *ast = NULL;
+
+ if (p) {
+ id = (int)strtol(p, NULL, 0);
+ }
+
+ ast_mutex_lock(&peerlink_lock);
+ if ((id >= 1) && (id <= CC_MAX_PEERLINKCHANNELS)) {
+ ast = peerlinkchannel[id].channel;
+ peerlinkchannel[id].channel = NULL;
+ }
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDI: peerlink %d allocated, peer is %s\n", id, (ast)?ast->name:"unlinked");
+ ast_mutex_unlock(&peerlink_lock);
+ return ast;
+}
+
+static void cc_destroy_all_peer_link_id(void)
+{
+ int i;
+
+ ast_mutex_lock(&peerlink_lock);
+ for (i = 1; i <= CC_MAX_PEERLINKCHANNELS; i++) {
+ /* remove entries */
+ peerlinkchannel[i].channel = NULL;
+ }
+ ast_mutex_unlock(&peerlink_lock);
+}
+#endif
+
/*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
static inline int dahdi_get_event(int fd)
@@ -467,6 +757,7 @@
time_t lastreset; /*!< time when unused channels were last reset */
long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
int sig;
+ unsigned int use_callingpres:1; /*!< used for no channel call */
struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
struct dahdi_pvt *crvs; /*!< Member CRV structs */
struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
@@ -564,6 +855,9 @@
ast_mutex_t lock;
struct ast_channel *owner; /*!< Our current active owner (if applicable) */
/*!< Up to three channels can be associated with this call */
+#ifdef HAVE_PRI
+ int dummychannel; /*!< Flag for dummy Channel. used for ccbsnr (shellscript) */
+#endif
struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
struct dahdi_subchannel subs[3]; /*!< Sub-channels */
@@ -652,6 +946,9 @@
unsigned int resetting:1;
unsigned int setup_ack:1;
#endif
+#ifdef HAVE_PRI
+ unsigned int ccringout:1; /*!< Append CC-Ringout facility */
+#endif
unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
struct mwisend_info mwisend_data;
struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
@@ -942,6 +1239,282 @@
#define GET_CHANNEL(p) ((p)->channel)
#endif
+#ifdef HAVE_PRI
+static inline int pri_nochannel_grab(struct dahdi_pri *pri)
+{
+ int res;
+ /* Grab the lock first */
+ do {
+ res = ast_mutex_trylock(&pri->lock);
+ if (res) {
+ /* Release the lock and try again */
+ usleep(1);
+ }
+ } while (res);
+ /* Then break the poll */
+ pthread_kill(pri->master, SIGURG);
+ return 0;
+}
+
+
+/*
+ * a new CCBS/CCNR id was received
+ */
+static struct ccbsnr_link *ccbsnr_new_id(int callreference, int ccbsnronprispan, q931_call *call, int type, char* callingnum, char *callernum,
+ char *callername, char *context, int priority, struct ast_channel *peer) {
+ struct ccbsnr_link *ccbsnr;
+
+ ccbsnr = ast_calloc(1, sizeof(*ccbsnr));
+ if (!ccbsnr) {
+ ast_log(LOG_ERROR, "Unable to allocate CCBS/CCNR struct.\n");
+ return NULL;
+ }
+
+ ccbsnr->age = time(NULL);
+ ccbsnr->type = type;
+ ccbsnr->call = call;
+ ccbsnr->handle = CCBS_HANDLE(ccbsnronprispan,callreference);
+ ccbsnr->peer = peer;
+ ccbsnr->priority = priority;
+ ccbsnr->state = CC_WAIT_ACK;
+ ast_copy_string(ccbsnr->callingnum, callingnum, sizeof(ccbsnr->callingnum));
+ ast_copy_string(ccbsnr->callernum, callernum, sizeof(ccbsnr->callernum));
+ ast_copy_string(ccbsnr->callername, callername, sizeof(ccbsnr->callername));
+ ast_copy_string(ccbsnr->context, context, sizeof(ccbsnr->context));
+
+ ast_mutex_lock(&ccbsnr_lock);
+ del_old_ccbsnr();
+ ccbsnr->next = ccbsnr_list;
+ ccbsnr_list = ccbsnr;
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ return ccbsnr;
+}
+
+
+/*
+ * Clear CCBS/CCNR links
+ */
+static void ccbsnr_clear_all(void)
+{
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link *tmp = NULL;
+ unsigned int span;
+ int cr;
+
+ ast_mutex_lock(&ccbsnr_lock);
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ tmp = ccbsnr;
+ ccbsnr = ccbsnr->next;
+ span = CCBS_SPAN(tmp->handle);
+ cr = CCBS_CR(tmp->handle);
+ ast_log(LOG_NOTICE, "ccbsnr_clear_all: ccbsnr found(%x) span %d\n", (int)tmp, span);
+ ast_free(tmp);
+ }
+
+ ccbsnr_list = NULL;
+ ast_mutex_unlock(&ccbsnr_lock);
+}
+
+
+static void ccbsnr_destroy_all_of_span(struct dahdi_pri *pri)
+{
+ int span = pri->span;
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link *prev = NULL;
+ struct ccbsnr_link *tmp = NULL;
+ q931_call *call;
+ unsigned int ccbs_span;
+ int cr;
+
+ ast_mutex_lock(&ccbsnr_lock);
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ ccbs_span = CCBS_SPAN(ccbsnr->handle);
+ cr = CCBS_CR(ccbsnr->handle);
+ if (ccbs_span == span) {
+ ast_log(LOG_NOTICE, "ccbsnr found(%x) ccbs_span %d\n", (int)ccbsnr, ccbs_span);
+
+ tmp = ccbsnr;
+ if (!prev) {
+ ccbsnr_list = ccbsnr->next;
+ } else {
+ prev->next = ccbsnr->next;
+ }
+ ccbsnr = ccbsnr->next;
+
+ if (tmp->call) {
+ call = pri_find_call(pri->pri, cr);
+ ast_log(LOG_NOTICE, "call found(%x)\n", (int)call);
+
+ if (call == tmp->call) {
+ ast_log(LOG_WARNING, "Q931Call(%x) cr(%x) found, hang it up it.\n", (int)call, cr);
+
+ pri_call_set_cc_operation(call, PRI_CC_CANCEL);
+ pri_hangup(pri->pri, call, -1);
+ pri_destroycall(pri->pri, call);
+ }
+ }
+ ast_free(tmp);
+ ast_log(LOG_WARNING, "Free ccbsnr-link (%x) ccbs_span %d\n", (int)tmp, ccbs_span);
+ } else {
+ prev = ccbsnr;
+ ccbsnr = ccbsnr->next;
+ }
+ }
+
+ ast_mutex_unlock(&ccbsnr_lock);
+}
+
+
+/*
+ * Destroy CCBS/CCNR links
+ */
+static void ccbsnr_destroy_all(void)
+{
+ struct ccbsnr_link *ccbsnr;
+ struct ccbsnr_link *tmp = NULL;
+ q931_call *call;
+ struct dahdi_pri *pri;
+ unsigned int span;
+ int cr;
+
+ ast_mutex_lock(&ccbsnr_lock);
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ tmp = ccbsnr;
+ ccbsnr = ccbsnr->next;
+ span = CCBS_SPAN(tmp->handle);
+ cr = CCBS_CR(tmp->handle);
+ ast_log(LOG_NOTICE, "ccbsnr_destroy_all: ccbsnr found(%x) span %d\n", (int)tmp, span);
+
+ if (tmp->call) {
+ pri = &pris[span - 1];
+
+ if (pri_nochannel_grab(pri)) {
+ ast_log(LOG_ERROR, "Failed to grab PRI!\n");
+ return;
+ }
+
+ call = pri_find_call(pri->pri, cr);
+ ast_log(LOG_NOTICE, "ccbsnr_destroy_all: call found(%x)\n", (int)call);
+
+ if (call == tmp->call) {
+ ast_log(LOG_WARNING, "ccbsnr_destroy_all(%x) cr(%x):Q931_call found, hang it up it.\n", (int)call, cr);
+
+ pri_call_set_cc_operation(call, PRI_CC_CANCEL);
+ pri_hangup(pri->pri, call, -1);
+ }
+
+ pri_rel(pri);
+ }
+ ast_free(tmp);
+ }
+
+ ccbsnr_list = NULL;
+ ast_mutex_unlock(&ccbsnr_lock);
+}
+
+
+/*
+ * on an activated CCBS, the remote party is now free
+ */
+static void ccbsnr_remote_user_free(unsigned int handle)
+{
+
+ struct ast_channel *ast;
+ struct ccbsnr_link *ccbsnr;
+ int state = AST_STATE_DOWN;
+ struct dahdi_pvt *dummy;
+
+ ast_verbose(VERBOSE_PREFIX_3 "ccbsnr_remote_user_free: handle %x\n", handle);
+
+ ast_mutex_lock(&ccbsnr_lock);
+
+ ccbsnr = ccbsnr_list;
+ while (ccbsnr) {
+ if (ccbsnr->handle == handle) {
+ break;
+ }
+ ccbsnr = ccbsnr->next;
+ }
+ ast_mutex_unlock(&ccbsnr_lock);
+
+ if (!(ccbsnr)) {
+ ast_log(LOG_ERROR, "DAHDI: CCBS/CCBR reference not found!\n");
+ return;
+ }
+
+ ast = ast_channel_alloc(0, state, 0, 0, "", "", "", 0, 0);
+ if (!ast) {
+ ast_log(LOG_ERROR, "Unable to allocate channel!\n");
+ return;
+ }
+
+ ast->tech = &dahdi_tech;
+ dummy = ast_calloc(1,sizeof(*dummy));
+ if (!dummy) {
+ ast_log(LOG_ERROR, "Unable to allocate dummy:struct dahdi_pvt!\n");
+ return;
+ }
+ ast_mutex_init(&dummy->lock);
+ dummy->dummychannel = 1;
+ ast->tech_pvt = dummy;
+ ast_string_field_build(ast, name, "CCBSNR/%x", ccbsnr->handle);
+
+ ast_verbose(VERBOSE_PREFIX_3 "ccbsnr_remote_user_free: ast=%x name=%s ast->_softhangup=%x ast->tech%x\n",
+ (int)ast, ast->name, ast->_softhangup, (int)ast->tech);
+
+ ast->_softhangup = 0;
+ memset(&ast->whentohangup, 0, sizeof(ast->whentohangup));
+
+ ast->priority = ccbsnr->priority;
+
+ if (ast->cid.cid_num) {
+ ast_free(ast->cid.cid_num);
+ }
+ ast->cid.cid_num = ast_strdup(ccbsnr->callernum);
+
+ if (ast->cid.cid_dnid) {
+ ast_free(ast->cid.cid_dnid);
+ }
+ ast->cid.cid_name = ast_strdup(ccbsnr->callername);
+
+ ast_copy_string(ast->context, ccbsnr->context, sizeof(ast->context));
+ ast_copy_string(ast->exten, ccbsnr->callingnum, sizeof(ast->exten));
+
+ ast_setstate(ast, state);
+ ast_verbose(VERBOSE_PREFIX_3 "ccbsnr_remote_user_free: ast_pbx_start:ast %x cc-req(%d)\n", (int)ast, ccbsnr->type);
+
+ if (ast_pbx_start(ast)) {
+ pri_call_set_cc_operation(ccbsnr->call, PRI_CC_CANCEL);
+
+ int ccbs_span = CCBS_SPAN(ccbsnr->handle);
+ struct dahdi_pri *ccbs_pri = &pris[ccbs_span - 1];
+
+ if (pri_nochannel_grab(ccbs_pri)) {
+ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
+ return;
+ }
+ pri_hangup(ccbs_pri->pri, ccbsnr->call, -1);
+ pri_rel(ccbs_pri);
+ ccbsnr->call = NULL;
+ ccbsnr_del_link(ccbsnr->handle);
+
+ ast_log(LOG_ERROR, "DAHDI: CCBS/CCNR: Unable to start pbx!\n");
+
+ return;
+ } else {
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI-span%d: started PBX for CCBS/CCNR callback (context:%s/callingnum:%s/prio:%d)callernum:%s callername:%s peer=%x\n",
+ CCBS_SPAN(ccbsnr->handle), ccbsnr->context, ccbsnr->callingnum, ccbsnr->priority, ccbsnr->callernum, ccbsnr->callername, (int)ccbsnr->peer);
+ ccbsnr->state = CC_WAIT_USER_A_ANSWER_N;
+ }
+
+ ast_module_ref(ast_module_info->self);
+}
+#endif
+
struct dahdi_pvt *round_robin[32];
#ifdef HAVE_PRI
@@ -2755,6 +3328,11 @@
#ifdef HAVE_PRI
if (p->pri) {
struct pri_sr *sr;
+ struct ast_channel *peer;
+ struct ccbsnr_link *cclink;
+ unsigned int state = 0;
+ char *callingnum;
+ char *callernum;
#ifdef SUPPORT_USERUSER
const char *useruser;
#endif
@@ -3008,6 +3586,57 @@
if (useruser)
pri_sr_set_useruser(sr, useruser);
#endif
+ callingnum = c + p->stripmsd + dp_strip;
+ callernum = l ? (l + ldp_strip) : NULL;
+
+ /* search ccbs-list */
+ cclink = ccbsnr_get_link_by_number(callingnum, callernum, &state);
+
+ if (p->ccringout) {
+ if (cclink) {
+ pri_sr_set_ccringout(sr, p->ccringout);
+ } else {
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI-Call: ccbsnr-link found. state(%d). Change to Dial without CC-Ringout\n", state);
+ p->ccringout = 0;
+ }
+ } else {
+ /* Normal Call */
+ if (cclink) {
+ int span = CCBS_SPAN(cclink->handle);
+ struct dahdi_pri *ccbs_pri;
+
+ switch (state) {
+ case CC_WAIT_ACK:
+ case CC_WAIT_USER_A_ANSWER_N:
+ case CC_INVOKED_A_RET:
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDI-Call: CCBS-List-Obj 0x%x: handle %x span(%d) peer=%x\n", \
+ (int)cclink, cclink->handle, span, (int)cclink->peer);
+
+ if (cclink->call) {
+ pri_call_set_cc_operation(cclink->call, PRI_CC_CANCEL);
+
+ ccbs_pri = &pris[span - 1];
+ if (ccbs_pri != p->pri) {
+ if (pri_nochannel_grab(ccbs_pri)) {
+ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
+ return -1;
+ }
+
+ pri_hangup(ccbs_pri->pri, cclink->call, -1);
+
+ pri_rel(ccbs_pri);
+ } else {
+ pri_hangup(p->pri->pri, cclink->call, -1);
+ }
+ }
+ cclink->call = NULL;
+ ccbsnr_del_link(cclink->handle);
+ break;
+ default:
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI-Call:wrong ccbsnr-link-state '%d'\n", state);
+ }
+ }
+ }
if (pri_setup(p->pri->pri, p->call, sr)) {
ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
@@ -3020,6 +3649,17 @@
pri_sr_free(sr);
ast_setstate(ast, AST_STATE_DIALING);
pri_rel(p->pri);
+ peer = cc_get_peer_link_id(pbx_builtin_getvar_helper(ast, "CCPEERLINKID"));
+ if (peer) {
+ char tmp[32];
+
+ pbx_builtin_setvar_helper(peer, "CCPEERLINKID", "0");
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI peer link is %x %s.\n", (int)peer, peer->name);
+
+ snprintf(tmp, sizeof(tmp) - 1, "%d", p->pri->span);
+ pbx_builtin_setvar_helper(peer, "CCBSNRONPRISPAN", tmp);
+ }
}
#endif
ast_mutex_unlock(&p->lock);
@@ -3129,6 +3769,509 @@
}
#ifdef HAVE_PRI
+static char *dahdi_qsig_ccbsnr_initialize_app = "DAHDIQsigCcbsnrInitialize";
+
+/*
+ * store the peer for future actions
+ */
+static int dahdi_qsig_ccbsnr_initialize_exec(struct ast_channel *ast, void *param)
+{
+ char buffer[32];
+ int id;
+
+ id = cc_add_peer_link_id(ast);
+
+ if (id >= 0) {
+ snprintf(buffer, sizeof(buffer) - 1, "%d", id);
+ pbx_builtin_setvar_helper(ast, "_CCPEERLINKID", buffer);
+ pbx_builtin_setvar_helper(ast, "_CCBSNRREQSTATE", "AVAILABLE");
+ pbx_builtin_setvar_helper(ast, "_CCBSNRONPRISPAN", "0");
+ }
+
+ ast_verbose(VERBOSE_PREFIX_3 "Added %s as DAHDI peer link.\n",
+ ast->name);
+
+ return 0;
+}
+
+#define CC_MAX_NOCHANNELS 256
+
+static char *dahdi_qsic_check_ccbsnr_app = "DAHDIQsigCheckCcbsnr";
+
+static int dahdi_qsig_check_ccbsnr_exec(struct ast_channel *ast, void *param)
+{
+
+#define MAX_DISSALOWED 4
+
+ char *data = (char *) param;
+ char *parse, *tok, *tokb;
+ int maxcount = 0;
+ char *dissalowed_callernum[MAX_DISSALOWED] = {NULL, NULL, NULL, NULL};
+ char *maxcounter = NULL;
+ char *callingnum = NULL;
+ char *callernum = NULL;
+ int count = 0;
+ int flag = 0;
+ char *c;
+ int cnt;
+
+ if (ast_strlen_zero(param)) {
+ ast_debug(1, "Check command requires arguments!\n");
+ return -1;
+ }
+
+ parse = ast_strdupa(data);
+ tok = strtok_r(parse, "|", &tokb);
+ if (!tok) {
+ ast_log(LOG_WARNING, "DAHDIQsigCheckCcbsnr requires at least maxcounter argument\n");
+ return -1;
+ }
+ maxcounter = tok;
+ if (*tokb != '|') {
+ tok = strtok_r(NULL, "|", &tokb);
+ if (!tok) {
+ ast_log(LOG_WARNING, "DAHDIQsigCheckCcbsnr without callingnum argument\n");
+ return -1;
+ }
+ callingnum = tok;
+ } else {
+ callingnum = "";
+ tokb++;
+ }
+
+ if (*tokb != '|') {
+ tok = strtok_r(NULL, "|", &tokb);
+ if (!tok) {
+ ast_log(LOG_NOTICE, "DAHDIQsigCheckCcbsnr without callernum argument\n");
+ return -1;
+ }
+ callernum = tok;
+ } else {
+ callernum = "";
+ tokb++;
+ }
+
+
+ /* Optional args 'dissalowed_callernum'*/
+ for (cnt = 0; cnt < MAX_DISSALOWED; cnt++) {
+ tok = strtok_r(NULL, "|", &tokb);
+ if (!tok) {
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDIQsigCheckCcbsnr without dissalowed-callernum argument\n");
+ } else {
+ dissalowed_callernum[cnt] = tok;
+ }
+ }
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnr: '%s' '%s' '%s'\n", maxcounter, callingnum, callernum);
+ for (cnt = 0; cnt < MAX_DISSALOWED; cnt++) {
+ if (dissalowed_callernum[cnt])
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnr: '%s'\n", dissalowed_callernum[cnt]);
+ }
+
+ maxcount = (int)strtol(maxcounter, NULL, 0);
+ if (maxcount > CC_MAX_NOCHANNELS) {
+ ast_debug(1, "DAHDIQsigCheckCcbsnr <maxcount> range:(%d - %d)\n", 0, CC_MAX_NOCHANNELS);
+ return -1;
+ } else if (!maxcount) {
+ maxcount = CC_MAX_NOCHANNELS;
+ }
+
+ if (ast_strlen_zero(callernum)) {
+ flag = 1;
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDIQsigCheckCcbsnr: no caller number - <callingnum>|<callernum>\n");
+ } else if (ast_strlen_zero(callingnum)) {
+ flag = 1;
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDIQsigCheckCcbsnr: no caller number - <callingnum>|<callernum>\n");
+ } else if (!strcmp(callernum, callingnum)) {
+ flag = 1;
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDIQsigCheckCcbsnr: caller number(%s) and calling number are equal\n", callernum);
+ } else {
+ for (c = callernum; *c; c++)
+ *c = tolower(*c);
+ for (cnt = 0; cnt < MAX_DISSALOWED; cnt++) {
+ if (dissalowed_callernum[cnt]) {
+ if (!strcmp(callernum, dissalowed_callernum[cnt])) {
+ flag = 1;
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDIQsigCheckCcbsnr: dissalowed_callernum - %s\n", dissalowed_callernum[cnt]);
+ break;
+ }
+ }
+ }
+ count = ccbsnr_count_callingnum(callingnum);
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDIQsigCheckCcbsnr: maxcount(%d) count(%d)\n", maxcount, count);
+ if (count >= maxcount) {
+ flag = 1;
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDIQsigCheckCcbsnr: count(%d) <callingnum>|<callernum>\n", count);
+ }
+ }
+
+ if (flag) {
+ ast_verbose(VERBOSE_PREFIX_3 "Set CCBSNRREQSTATE to NOTAVAILABLE\n");
+ pbx_builtin_setvar_helper(ast, "CCBSNRREQSTATE", "NOTAVAILABLE");
+ }
+
+ return 0;
+}
+
+
+static char *dahdi_qsic_clear_nochannel_app = "DAHDIQsigClearNoChannel";
+
+static int dahdi_qsig_clear_nochannel_exec(struct ast_channel *ast, void *param)
+{
+ char *callingnum, *callernum;
+ char *data = (char *) param;
+
+ struct ccbsnr_link *cclink;
+ unsigned int state = 0;
+ struct dahdi_pri *pri;
+ unsigned int span;
+ int cr;
+ q931_call *call;
+
+ if (ast_strlen_zero(data)) {
+ ast_debug(1, "Clear command requires arguments!\n");
+ return -1;
+ }
+
+ callingnum = strsep(&data, "|");
+ callernum = data;
+
+ if ((!callingnum) || (!callernum)) {
+ ast_debug(1, "DAHDIQsigClearNoChannel requires <callingnum>|<callernum>\n");
+ return -1;
+ }
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnr: '%s' '%s'\n", callingnum, callernum);
+
+ cclink = ccbsnr_get_link_by_number(callingnum, callernum, &state);
+ if (cclink) {
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnr: state(%d)\n", state);
+
+ switch (state) {
+ case CC_WAIT_ACK:
+ case CC_WAIT_USER_A_ANSWER_N:
+ case CC_INVOKED_A_RET:
+ if (cclink->call) {
+ span = CCBS_SPAN(cclink->handle);
+ pri = &pris[span - 1];
+
+ if (pri_nochannel_grab(pri)) {
+ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
+ return -1;
+ }
+ cr = CCBS_CR(cclink->handle);
+ call = pri_find_call(pri->pri, cr);
+
+ ast_log(LOG_NOTICE, "destroy cclink: call found(%x)\n", (int)call);
+
+ if (call == cclink->call) {
+ ast_log(LOG_NOTICE, "destroy call(%x) cr(%x):Q931_call found, hang it up it.\n", (int)call, cr);
+
+ pri_call_set_cc_operation(call, PRI_CC_CANCEL);
+ pri_hangup(pri->pri, call, -1);
+ }
+ pri_rel(pri);
+ }
+ ast_mutex_lock(&ccbsnr_lock);
+ cclink->call = NULL;
+ ast_mutex_unlock(&ccbsnr_lock);
+ ccbsnr_del_link(cclink->handle);
+ break;
+ default:
+ ast_verbose(VERBOSE_PREFIX_2 "PRI_EVENT_HANGUP:wrong state '%d'\n", state);
+ }
+ } else {
+ ast_verbose(VERBOSE_PREFIX_2 "dahdi_qsig_clear_nochannel: CCBS-List-Obj for callingnum(%s) callernum(%s) not found\n", callingnum, callernum);
+ return 0;
+ }
+ return 0;
+
+}
+
+
+static char *dahdi_qsic_ccbsnr_request_app = "DAHDIQsigCcbsnrRequest";
+
+static int dahdi_qsig_ccbsnr_request_exec(struct ast_channel *ast, void *param)
+{
+ int type;
+ char *ccbsnrtype, *callingnum, *callernum, *callername, *context, *priority;
+ char *data = (char *) param;
+
+ const char *ccbsnronprispan;
+ unsigned int prispan;
+ char *c, *l, *n;
+ char *s = NULL;
+ int dp_strip;
+ int ldp_strip;
+ struct pri_sr *sr;
+ int pridialplan;
+ int prilocaldialplan;
+ l = NULL;
+ n = NULL;
+
+ struct dahdi_pri *pri;
+ struct ccbsnr_link *cclink;
+ q931_call *call;
+
+ /* sets for no channel call */
+ int channel = 0;
+ int exclusive = 1;
+ int nonisdn = 0;
+ int transmode = -1;
+ int userl1 = ast->transfercapability;
+ int cref = 0;
+
+ if (ast_strlen_zero(data)) {
+ ast_debug(1, "CCBScommand requires arguments!\n");
+ return -1;
+ }
+
+ ccbsnrtype = strsep(&data, "|");
+ callingnum = strsep(&data, "|");
+ callernum = strsep(&data, "|");
+ callername = strsep(&data, "|");
+ context = strsep(&data, "|");
+ priority = data;
+
+ if ((!ccbsnrtype) || (!callingnum) || (!callernum) || (!callername) || (!context) || (!priority)) {
+ ast_debug(1, "DAHDIQsigCcbsnrRequest requires <CCBR/CCNR>|<callingnum>|<callernum>|<callername>|<context>|<priority>\n");
+ return -1;
+ }
+
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnr: '%s' '%s' '%s' '%s' '%s' '%s'\n",
+ ccbsnrtype, callingnum, callernum, callername, context, priority);
+
+ if (!strcmp(callernum, callingnum)) {
+ ast_debug(1, "DAHDIQsigCcbsnrRequest: caller number(%s) and calling number are equal\n", callernum);
+ return -1;
+ }
+
+ if (!strcmp(ccbsnrtype, "CCBS"))
+ type = PRI_CC_CCBSREQUEST;
+ else if (!strcmp(ccbsnrtype, "CCNR"))
+ type = PRI_CC_CCNRREQUEST;
+ else {
+ ast_verbose(VERBOSE_PREFIX_2 "DAHDIQsigCcbsnrRequest requires <CCBS/CCNR>|<callingnum>|<callernum>|<callername>|<context>|<priority>\n");
+ return -1;
+ }
+
+ ccbsnronprispan = pbx_builtin_getvar_helper(ast, "CCBSNRONPRISPAN");
+ ast_verbose(VERBOSE_PREFIX_3 "DAHDI ccbsnronprispan: '%s'\n", ccbsnronprispan);
+
+ if (ast_strlen_zero(ccbsnronprispan)) {
+ ast_debug(1, "DAHDIQsigCcbsnrRequest: Use initialize befor use this funktion\n");
+ return -1;
+ }
+
+ prispan = (int)strtol(ccbsnronprispan, NULL, 0);
+
+ if ((prispan < 1) || (prispan > NUM_SPANS)) {
+ ast_verbose(VERBOSE_PREFIX_2 "DAHDI:Invalid span %d. Should be a number %d to %d\n", prispan, 1, NUM_SPANS);
+ return -1;
+ }
+
+ pri = &pris[prispan-1];
+ if (pri_nochannel_grab(pri)) {
+ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
+ return -1;
+ }
+
+ if (!(call = pri_new_nochannel_call(pri->pri, &cref))) {
+ ast_log(LOG_WARNING, "Unable to create no channel call on span %d\n", prispan);
+ pri_rel(pri);
+ return -1;
+ }
+
+ if (!(sr = pri_sr_new())) {
+ ast_log(LOG_WARNING, "Failed to allocate setup request for no channel on span %d\n", prispan);
+ pri_rel(pri);
+ }
+ pri_sr_set_no_channel_call(sr);
+ pri_sr_set_ccbsnr(sr, type);
+
+ channel |= prispan << 8 | exclusive << 16;
+ pri_sr_set_channel(sr, channel, exclusive, nonisdn);
+ pri_sr_set_bearer(sr, transmode, userl1);
+ if (pri->facilityenable)
+ pri_facility_enable(pri->pri);
+
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDI:Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
+ dp_strip = 0;
+ pridialplan = pri->dialplan - 1;
+ c = callingnum;
+ if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
+ if (strncmp(c, pri->internationalprefix, strlen(pri->internationalprefix)) == 0) {
+ if (pridialplan == -2) {
+ dp_strip = strlen(pri->internationalprefix);
+ }
+ pridialplan = PRI_INTERNATIONAL_ISDN;
+ } else if (strncmp(c, pri->nationalprefix, strlen(pri->nationalprefix)) == 0) {
+ if (pridialplan == -2) {
+ dp_strip = strlen(pri->nationalprefix);
+ }
+ pridialplan = PRI_NATIONAL_ISDN;
+ } else {
+ pridialplan = PRI_LOCAL_ISDN;
+ }
+ }
+ while (c[0] > '9' && c[0] != '*' && c[0] != '#') {
+ switch (c[0]) {
+ 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))
+ ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
+ }
+ c++;
+ }
+ pri_sr_set_called(sr, c + dp_strip, pridialplan, s ? 1 : 0);
+
+ l = callernum;
+ n = callername;
+ ldp_strip = 0;
+ prilocaldialplan = pri->localdialplan - 1;
+ if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
+ if (strncmp(l, pri->internationalprefix, strlen(pri->internationalprefix)) == 0) {
+ if (prilocaldialplan == -2) {
+ ldp_strip = strlen(pri->internationalprefix);
+ }
+ prilocaldialplan = PRI_INTERNATIONAL_ISDN;
+ } else if (strncmp(l, pri->nationalprefix, strlen(pri->nationalprefix)) == 0) {
+ if (prilocaldialplan == -2) {
+ ldp_strip = strlen(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", *c > 'Z' ? "NPI" : "TON", *c);
+ }
+ l++;
+ }
+ }
+
+ pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
+ pri->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
+
+ cclink = ccbsnr_new_id(cref, prispan, call, type, callingnum, callernum,
+ callername, context, (int)strtol(priority, NULL, 0), ast);
+ if (!cclink) {
+ ast_log(LOG_WARNING, "Unable to allocate ccbsnr list object. Aborting!\n");
+ pri_rel(pri);
+ pri_sr_free(sr);
+ return -1;
+ }
+
+ if (pri_setup(pri->pri, cclink->call, sr)) {
+ unsigned int handle = CCBS_HANDLE(prispan, cref);
+ ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
+ c + dp_strip, dialplan2str(pri->dialplan));
+
+ pri_hangup(pri->pri, cclink->call, -1);
+ cclink->call = NULL;
+ ccbsnr_del_link(handle);
+ pri_rel(pri);
+ pri_sr_free(sr);
+
+ return -1;
+ }
+
+ pri_sr_free(sr);
+ ast_setstate(ast, AST_STATE_DIALING);
+ pri_rel(pri);
+
+ return 0;
+}
+
+
static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
@@ -3344,6 +4487,21 @@
ast_mutex_lock(&p->lock);
+#ifdef HAVE_PRI
+ if (p->dummychannel == 1) {
+ ast_verb(3, "Hangup: dummy-channel(%s)\n", ast->name);
+ ast_verb(3, "Hangup:tech_pvt=%x q931_call=%x\n", (int)p, (int)p->call);
+
+ ast->tech_pvt = NULL;
+ ast_mutex_unlock(&p->lock);
+ ast_module_unref(ast_module_info->self);
+ ast_mutex_destroy(&p->lock);
+ ast_free(p);
+ return 0;
+ }
+ p->ccringout = 0;
+#endif
+
idx = dahdi_get_index(ast, p, 1);
if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
@@ -9041,6 +10199,9 @@
ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
pris[span].resetinterval = conf->pri.resetinterval;
+ if (chan_sig == SIG_PRI) {
+ pris[span].use_callingpres = conf->chan.use_callingpres;
+ }
tmp->pri = &pris[span];
tmp->prioffset = offset;
@@ -9722,6 +10883,11 @@
p->digital = 1;
if (tmp)
tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
+#ifdef HAVE_PRI
+ } else if (opt == 'q') {
+ /* Append CC-Ringout facility */
+ p->ccringout = 1;
+#endif
} else {
ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
}
@@ -11215,6 +12381,7 @@
p->inalarm = 1;
}
}
+ ccbsnr_destroy_all_of_span(pri);
}
break;
case PRI_EVENT_RESTART:
@@ -11755,215 +12922,426 @@
}
break;
case PRI_EVENT_FACILITY:
- chanpos = pri_find_principle(pri, e->facility.channel);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Facility requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->facility.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Facility requested on channel %d/%d not in use on span %d\n",
- PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
- } else {
- int i;
-
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ {
+ unsigned int handle;
+ int channel = e->facility.channel;
+ int ccbsnronprispan = PRI_SPAN(channel);
+ int explicit = PRI_EXPLICIT(channel);
+ int i;
+
+ channel = PRI_CHANNEL(channel);
+
+ ast_verbose(VERBOSE_PREFIX_4 "PRI_EVENT_CC_FACILITY e->facility.channel(0x%x) span(%d) explicit(%d) channel(%d)\n", \
+ e->facility.channel, ccbsnronprispan, explicit, channel);
+ if (channel == 0) {
for (i = 0; i < e->facility.subcmds.counter_subcmd; i++) {
subcommand *subcmd = &e->facility.subcmds.subcmd[i];
-
switch (subcmd->cmd) {
- case CMD_CONNECTEDLINE:
+ case CMD_CC_EXECPOSIBLE_INV:
{
- struct ast_party_connected_line connected;
- cmd_connectedline *cmdcl;
- struct ast_channel *owner = pri->pvts[chanpos]->owner;
-
- /* Update the connected line information on the other channel */
- ast_party_connected_line_init(&connected);
- cmdcl = &subcmd->connectedline;
- connected.id.number = cmdcl->connected.id.number;
- connected.id.name = cmdcl->connected.id.name;
- connected.id.number_type = cmdcl->connected.id.number_type;
- connected.id.number_presentation = pri_to_ast_presentation(cmdcl->connected.id.number_presentation);
- connected.source = pri_to_ast_connected_line_update_source(cmdcl->connected.source);
- ast_queue_connected_line_update(owner, &connected);
-
- ast_copy_string(pri->pvts[chanpos]->lastcid_num, cmdcl->connected.id.number, sizeof(pri->pvts[chanpos]->lastcid_num));
- ast_copy_string(pri->pvts[chanpos]->lastcid_name, cmdcl->connected.id.name, sizeof(pri->pvts[chanpos]->lastcid_name));
-
- pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
- }
- break;
- case CMD_REDIRECTING:
- {
- struct ast_party_redirecting redirecting = {{0,},};
- cmd_redirecting *cmdr;
- struct ast_channel *owner = pri->pvts[chanpos]->owner;
-
- cmdr = &subcmd->redirecting;
- redirecting.from.number = cmdr->redirecting.from.number;
- redirecting.from.name = cmdr->redirecting.from.name;
- redirecting.from.number_type = cmdr->redirecting.from.number_type;
- redirecting.from.number_presentation = pri_to_ast_presentation(cmdr->redirecting.from.number_presentation);
- redirecting.to.number = cmdr->redirecting.to.number;
- redirecting.to.name = cmdr->redirecting.to.name;
- redirecting.to.number_type = cmdr->redirecting.to.number_type;
- redirecting.to.number_presentation = pri_to_ast_presentation(cmdr->redirecting.to.number_presentation);
- redirecting.count = 0;
- redirecting.reason = pri_to_ast_reason(cmdr->redirecting.reason);
- ast_queue_redirecting_update(owner, &redirecting);
+ int cr = e->facility.cref;
+ ast_verbose(VERBOSE_PREFIX_4 "Facility cc-execposible INV cr %d channel %d/%d, span %d\n",
+ cr, ccbsnronprispan, channel, pri->span);
+
+ handle = CCBS_HANDLE(ccbsnronprispan,cr);
+ unsigned int state = 0;
+ ast_verbose(VERBOSE_PREFIX_4 "Facility cc-execposible: handle=%x\n", handle);
+ if (ccbsnr_get_link(handle, &state) != NULL) {
+ if (state == CC_INVOKED_A_RET) {
+ ast_verbose(VERBOSE_PREFIX_4 "DAHDI ccbsnr_remote_user_free: state '%d'\n", state);
+ ccbsnr_remote_user_free(handle);
+ }
+ } else {
+ ast_verbose(VERBOSE_PREFIX_3 "Facility cc-execposible: List-obj not found - handle=%x state=%d\n", handle, state);
[... 693 lines stripped ...]
More information about the asterisk-commits
mailing list