[libpri-commits] rmudgett: branch 1.4 r1746 - /branches/1.4/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Fri May 28 13:44:00 CDT 2010
Author: rmudgett
Date: Fri May 28 13:43:57 2010
New Revision: 1746
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1746
Log:
ETSI Call Waiting support.
Add the ability to announce a call to an endpoint when there are no B
channels available. A call waiting call is a SETUP message with no B
channel selected.
Relevant specification: EN 300 056, EN 300 057, EN 300 058
Review: https://reviewboard.asterisk.org/r/569/
Modified:
branches/1.4/libpri.h
branches/1.4/pri.c
branches/1.4/pri_internal.h
branches/1.4/pri_q931.h
branches/1.4/q931.c
Modified: branches/1.4/libpri.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/libpri.h?view=diff&rev=1746&r1=1745&r2=1746
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Fri May 28 13:43:57 2010
@@ -98,6 +98,7 @@
#define PRI_EVENT_RETRIEVE 24 /* RETRIEVE request received */
#define PRI_EVENT_RETRIEVE_ACK 25 /* RETRIEVE_ACKNOWLEDGE received */
#define PRI_EVENT_RETRIEVE_REJ 26 /* RETRIEVE_REJECT received */
+#define PRI_EVENT_CONNECT_ACK 27 /* CONNECT_ACKNOWLEDGE received */
/* Simple states */
#define PRI_STATE_DOWN 0
@@ -1160,6 +1161,13 @@
struct pri_subcommands *subcmds;
};
+struct pri_event_connect_ack {
+ int e;
+ int channel;
+ q931_call *call;
+ struct pri_subcommands *subcmds;
+};
+
typedef union {
int e;
pri_event_generic gen; /* Generic view */
@@ -1184,6 +1192,7 @@
struct pri_event_retrieve retrieve;
struct pri_event_retrieve_ack retrieve_ack;
struct pri_event_retrieve_rej retrieve_rej;
+ struct pri_event_connect_ack connect_ack;
} pri_event;
struct pri;
@@ -1284,9 +1293,32 @@
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
-/* Answer the call on the given channel (ignored if you called acknowledge already).
+/* Answer(CONNECT) the call on the given channel.
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
+
+/*!
+ * \brief Send the manual CONNECT_ACKNOWLEDGE message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param channel Selected channel to assign to the call waiting call.
+ * Zero if do not include the channel id ie in the CONNECT_ACKNOWLEDGE message.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_connect_ack(struct pri *ctrl, q931_call *call, int channel);
+
+/*!
+ * \brief Set the manual CONNECT_ACKNOWLEDGE message enable flag.
+ *
+ * \param ctrl D channel controller.
+ * \param enable TRUE to enable manual CONNECT_ACKNOWLEDGE message feature.
+ *
+ * \return Nothing
+ */
+void pri_connect_ack_enable(struct pri *ctrl, int enable);
/*!
* \brief Give connected line information to a call
Modified: branches/1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri.c?view=diff&rev=1746&r1=1745&r2=1746
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Fri May 28 13:43:57 2010
@@ -507,6 +507,7 @@
{ PRI_EVENT_RETRIEVE, "Retrieve" },
{ PRI_EVENT_RETRIEVE_ACK, "Retrieve ACK" },
{ PRI_EVENT_RETRIEVE_REJ, "Retrieve Rej" },
+ { PRI_EVENT_CONNECT_ACK, "Connect ACK" },
/* *INDENT-ON* */
};
@@ -691,6 +692,22 @@
if (!pri || !call)
return -1;
return q931_connect(pri, call, channel, nonisdn);
+}
+
+int pri_connect_ack(struct pri *ctrl, q931_call *call, int channel)
+{
+ if (!ctrl || !call) {
+ return -1;
+ }
+ return q931_connect_acknowledge(ctrl, call, channel);
+}
+
+void pri_connect_ack_enable(struct pri *ctrl, int enable)
+{
+ if (ctrl) {
+ ctrl = PRI_MASTER(ctrl);
+ ctrl->manual_connect_ack = enable ? 1 : 0;
+ }
}
/*!
Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=1746&r1=1745&r2=1746
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Fri May 28 13:43:57 2010
@@ -108,6 +108,7 @@
unsigned int cc_support:1;/* TRUE if upper layer supports call completion. */
unsigned int transfer_support:1;/* TRUE if the upper layer supports ECT */
unsigned int aoc_support:1;/* TRUE if can send AOC events to the upper layer. */
+ unsigned int manual_connect_ack:1;/* TRUE if the CONNECT_ACKNOWLEDGE is sent with API call */
/* MDL variables */
int mdl_error;
Modified: branches/1.4/pri_q931.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_q931.h?view=diff&rev=1746&r1=1745&r2=1746
==============================================================================
--- branches/1.4/pri_q931.h (original)
+++ branches/1.4/pri_q931.h Fri May 28 13:43:57 2010
@@ -475,6 +475,7 @@
extern int q931_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
+int q931_connect_acknowledge(struct pri *ctrl, q931_call *call, int channel);
extern int q931_release(struct pri *pri, q931_call *call, int cause);
Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=1746&r1=1745&r2=1746
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Fri May 28 13:43:57 2010
@@ -1063,6 +1063,10 @@
}
if (call->chanflags & FLAG_EXCLUSIVE) {
/* Channel is exclusive */
+ if (!(ie->data[pos] & 0x03)) {
+ /* An exclusive no channel id ie is to be discarded. */
+ return 0;
+ }
ie->data[pos] |= 0x08;
} else if (!call->chanflags) {
/* Don't need this IE */
@@ -5179,20 +5183,6 @@
return res;
}
-static int connect_acknowledge_ies[] = { -1 };
-
-static int gr303_connect_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
-
-static int q931_connect_acknowledge(struct pri *ctrl, q931_call *c)
-{
- if (ctrl->subchannel && !ctrl->bri) {
- if (ctrl->localtype == PRI_CPE)
- return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
- } else
- return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
- return 0;
-}
-
/*!
* \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
*
@@ -5216,6 +5206,49 @@
}
}
return call;
+}
+
+static int connect_ack_ies[] = { -1 };
+static int connect_ack_w_chan_id_ies[] = { Q931_CHANNEL_IDENT, -1 };
+static int gr303_connect_ack_ies[] = { Q931_CHANNEL_IDENT, -1 };
+
+int q931_connect_acknowledge(struct pri *ctrl, q931_call *call, int channel)
+{
+ int *use_ies;
+ struct q931_call *winner;
+
+ winner = q931_find_winning_call(call);
+ if (!winner) {
+ return -1;
+ }
+
+ if (winner != call) {
+ UPDATE_OURCALLSTATE(ctrl, call, Q931_CALL_STATE_ACTIVE);
+ call->peercallstate = Q931_CALL_STATE_ACTIVE;
+ }
+ UPDATE_OURCALLSTATE(ctrl, winner, Q931_CALL_STATE_ACTIVE);
+ winner->peercallstate = Q931_CALL_STATE_ACTIVE;
+ if (channel) {
+ winner->ds1no = (channel & 0xff00) >> 8;
+ winner->ds1explicit = (channel & 0x10000) >> 16;
+ winner->channelno = channel & 0xff;
+ winner->chanflags &= ~FLAG_PREFERRED;
+ winner->chanflags |= FLAG_EXCLUSIVE;
+ }
+ use_ies = NULL;
+ if (ctrl->subchannel && !ctrl->bri) {
+ if (ctrl->localtype == PRI_CPE) {
+ use_ies = gr303_connect_ack_ies;
+ }
+ } else if (channel) {
+ use_ies = connect_ack_w_chan_id_ies;
+ } else {
+ use_ies = connect_ack_ies;
+ }
+ if (use_ies) {
+ return send_message(ctrl, winner, Q931_CONNECT_ACKNOWLEDGE, use_ies);
+ }
+ return 0;
}
/*!
@@ -5693,6 +5726,8 @@
release_compl = 1;
break;
}
+ /* Fall through */
+ case PRI_CAUSE_INCOMPATIBLE_DESTINATION:
/* See Q.931 Section 5.3.2 a) */
switch (c->ourcallstate) {
case Q931_CALL_STATE_NULL:
@@ -5704,6 +5739,13 @@
*/
disconnect = 0;
release_compl = 1;
+ break;
+ case Q931_CALL_STATE_CONNECT_REQUEST:
+ /*
+ * Send RELEASE because the B channel negotiation failed
+ * for call waiting.
+ */
+ disconnect = 0;
break;
default:
/*
@@ -7291,8 +7333,6 @@
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
break;
}
- UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
- c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
ctrl->ev.e = PRI_EVENT_ANSWER;
ctrl->ev.answer.subcmds = &ctrl->subcmds;
@@ -7304,7 +7344,12 @@
libpri_copy_string(ctrl->ev.answer.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.answer.useruserinfo));
c->useruserinfo[0] = '\0';
- q931_connect_acknowledge(ctrl, c);
+ if (!PRI_MASTER(ctrl)->manual_connect_ack) {
+ q931_connect_acknowledge(ctrl, c, 0);
+ } else {
+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CONNECT_REQUEST);
+ c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
+ }
if (c->cis_auto_disconnect && c->cis_call) {
/* Make sure WE release when we initiate a signalling only connection */
@@ -7390,14 +7435,26 @@
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break;
}
- if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
- !(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
- (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG))) {
- q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
- break;
- }
- UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
- c->peercallstate = Q931_CALL_STATE_ACTIVE;
+ switch (c->ourcallstate) {
+ default:
+ if (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG) {
+ q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
+ break;
+ }
+ /* Fall through */
+ case Q931_CALL_STATE_CONNECT_REQUEST:
+ case Q931_CALL_STATE_ACTIVE:
+ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
+ c->peercallstate = Q931_CALL_STATE_ACTIVE;
+ if (PRI_MASTER(ctrl)->manual_connect_ack) {
+ ctrl->ev.e = PRI_EVENT_CONNECT_ACK;
+ ctrl->ev.connect_ack.subcmds = &ctrl->subcmds;
+ ctrl->ev.connect_ack.channel = q931_encode_channel(c);
+ ctrl->ev.connect_ack.call = c->master_call;
+ return Q931_RES_HAVEEVENT;
+ }
+ break;
+ }
break;
case Q931_STATUS:
if (missingmand) {
More information about the libpri-commits
mailing list